Unity3D 学习笔记

 

顶点吸附        选择一个目标,按住V不放,用鼠标拖动物体合并后,松开V,实现合并
3D          选择Persp交互模式
2D          选择ISO交互模式

 

坐标

坐标:          X红色,Y绿色,Z蓝色
世界坐标:        整个场景的固定坐标
本地坐标:        物体自身坐标,随旋转而变化

 

保存场景
选择File→save scene

 

创建立方体
1:创建空物体:GameObject-Create Empty
2:创建网格过滤器:Component-Mesh-Mesh Filter
设置mesh属性
3:创建网格渲染器
Compinent-mesh-mesh Renderer
设置材质Materials属性

 

Rendering Mode渲染模式
渲染模式
Opaque           不透明,默认
Transparent       透明,半透明,如玻璃
Cutout          镂空,用于完全透明,或完全不透明,如栅栏
Fade          渐变,用于需要淡入淡出的物体

Material         材质着色器 shader的实例(可创建物体的质地,纹理,光滑,透明,反射率,折射率,发光度等)

X            向上移动
Y            下移动
Z            前移动

Transform
Posituon          位置坐标x,y,z
Rotation          旋转X,Y,Z
Scale            缩放X,Y,Z 1:1:1模型大小比例

 

创建流程
Project →Scene→GameObject→Component
项目→场景→物体→组件

Project →Scene→GameObject→Component

 


子父物体
创建一个物体,将一个或者多个物体拖拽到第一个物体上,就诞生了子父物体关系
子物体继承父物体属性,但子物体不影响父物体

 


Material材质着色器
shader的实例(可创建物体的质地,纹理,光滑,透明,反射率,折射率,发光度等)

创建一个materia
右键Project→Create→Material

如果一个物体没有Mesh Renderer 则无法拖拽materia 到该物体,创建一个即可

 

 

纹理,着色器,材质的关系
1:Shader(着色器)
2:materia(面板) 选什么shader 就拥有什么组件面板内容
3:Mesh Renderer 组件

着色器 纹理 着色
Shader→materia→color

//把一个图片放到物体上
贴图→materia材质→Mesh Renderer →物体

//改颜色
Game object物体→Mesh Renderer 组件 →materia材质→Color

 

 

sky box
三种模式
1:6 sided         需要提供六张图片来自 上下左右前后 把整个空间包围起来,组成天空
2:Cubemap        自带太阳的天空模式
3:procedural          提供简单的修改天地的颜色

 

修改天空的背景颜色和图片
1:project→materia材质→点击创建后的材质选择shader更改为skybox→选择模式
2:找到Camera→ADD Component→搜索skybox→Custom skybox→把创建好的skybox 拖进去即可

Camera下的Culling Mask
勾选什么,就将勾选内容渲染显示到游戏界面中

 

 

拉近和放大游戏内镜头
Camera下:
Orthographic       2D模式游戏镜头
Persoective        3D模式游戏镜头

3D模式下:
Field of View       数值越小镜头越近,数值越大镜头越远


快速定位摄像机位置
选中一个物体,按ctrl+shift+f

若游戏中存在多个Camera
Camera 下的 Depth值 越大,谁就在最上层显示

例如:想在游戏中显示小地图,就可以把小地图的camera的depth值调大于 主摄像头的 depth值即可
如果想把小地图的边界多余的空白部分去除,则勾选该摄像机→Camera→Clear Flags→选择Depth Only

 

添加层
第一步:点击物体→Layers→右边下拉选项→ADDLayes
第二步:选择层
Layes→右边下拉框选择刚才创建的Layes

 

遮挡剔除
如果一个场景中存在较为密集的物体且大部分被遮挡时,可以使用 遮挡剔除

当物体被另一个物体完全遮挡后CPU仍然需要计算让GPU渲染
怎么避免这种情况呢?
使用Instant Occlusion Culling 插件即可剔除被遮挡的物体,从而降低渲染的数量

 

全局光照

Global Illumination    简称GI 全局光照
能够计算直接光,间接光,环境光,反射光的光照系统
通过GI算法可以使渲染出来的环境光照效果更为真实丰富

直接光
从官员直接发出的光,通过Light组件实现
Type:四种类型

Directional Light      平行光
Point Light       点光源
Spot Light        聚光灯
Area Light        区域光

Range         范围,仅适用点光源和聚光灯
Spot Angle       聚光角度,只适用于聚光灯
Color          光线的颜色
Intensity        光线的照射强度
Culling Mask      选择遮蔽层,简单来说,就是要照射的层Layer

 

阴影
Mesh Renderer下→Cast Shandows

 

 

声音
创建声音源
Hierarchy右键Audio→Audio Source

Uinty 支持的音频文件格式
    mp3

    ogg

    wav

    aif

    mod

    s3m

    xm

声音分为2D 3D两类

3D声音:      有空间感,近大远小
2D声音:      适合背景音乐

在场景中产生声音,主要依靠两个重要组件:
Audio Listener       音频监听器:接受场景中的音频源Audio
Source          发出的声音,通过计算机的扬声器播放声音

Audio Source        音频源

 

音频源:
--Audio Clip           音频编辑:需要播放的音频资源.
--Mute              静音:如果启用,播放音频没有声音
--Play             On Awake 唤醒播放:勾选后场景启动时自动播放
--Loop             循环播放音频
--Volume            音量大小
--Pitch             音调:通过改变音调调节音频播放速度,1时正常播放速度
--Stereo Pan          2D声音设置左右声道
--Spatial Blend         2D与3D声音切换

 

 

安装VSTU2013
Visual Studio Tools for Unity
(VSTU)是 Visual Studio 的 Unity 插件,
可以使用 Visual Studio 构建 Unity 游戏。

 


Uinty支持三种高级变成语言:
C#,javascript,Boo Script
生成.cs脚本
脚本就是附加在游戏物体上用于定义游戏对象行为的指令代码

写好的类必须继承MonoBehaviour才能把脚本挂到物体上,默认在uinty中生成c#script代码自动继承
public class 类名:MonoBehaviour

 


序列化字段SerializeField
作用:在编辑器中显示私有变量
实例:
[SerializeField]
int a = 100;

//在编辑器中隐藏属性设置
[HideInInspector]
int b = 10;

//在编辑器中显示可以设置一个范围
[Range(0,100)]
public int a;

脚本只写:
字段
方法

不写构造函数

 

 

生命周期
初始化阶段方法
执行顺序
Awake>Start

Awake         创建游戏对象 立即执行 作用:初始化
Start          创建游戏对象 脚本启用才执行 作用:初始化

OnEnable         当可用,每当脚本对象启用时调用

 


游戏逻辑方法


private void FixedUpdate(){
    //执行时机:每隔固定(默认0.02秒)执行一次,时间可以修改
    //适用性:适合对物体物理操作(移动,旋转)不会受渲染影响
    //渲染时间不固定(每帧渲染量不同,机器性能不同)
}

 

prinvate void Update(){
  //执行时机:渲染帧执行,执行间隔不固定
  //适用性:处理游戏逻辑
  但是一般移动都写到Update里
}


LateUpdate 延迟更新
例如在Update 里移动了,然后可以把摄像机的跟随移动代码写道 LateUpdate里

 


输入事件方法
OnMouseEnter 鼠标移入,鼠标移入到当前Collider时调用
OnMouseOver 鼠标经过
OnMouseExit 鼠标离开
OnMouseDown 鼠标按下
OnMouseUp 鼠标抬起

 


鼠标指针类事件(API2019.3)
独立输入模块和触摸输入模块支持的事件由接口提供,通过实现该接口即可在 MonoBehaviour 上实现这些事件。

如果配置了有效的事件系统,则会在正确的时间调用事件。

IPointerEnterHandler - OnPointerEnter        - 当指针进入对象时调用
IPointerExitHandler - OnPointerExit         - 当指针退出对象时调用
IPointerDownHandler - OnPointerDown       - 在对象上按下指针时调用
IPointerUpHandler - OnPointerUp         - 松开指针时调用(在指针正在点击的游戏对象上调用)
IPointerClickHandler - OnPointerClick       - 在同一对象上按下再松开指针时调用
IInitializePotentialDragHandler          - OnInitializePotentialDrag - 在找到拖动目标时调用,可用于初始化值
IScrollHandler - OnScroll            - 当鼠标滚轮滚动时调用
IUpdateSelectedHandler             - OnUpdateSelected - 每次勾选时在选定对象上调用
ISelectHandler - OnSelect            - 当对象成为选定对象时调用
IDeselectHandler - OnDeselect         - 取消选择选定对象时调用
IMoveHandler - OnMove            - 发生移动事件(上、下、左、右等)时调用
ISubmitHandler - OnSubmit           - 按下 Submit 按钮时调用
ICancelHandler - OnCancel           - 按下 Cancel 按钮时调用

 

 


拖拽类事件(API2019.3)
IBeginDragHandler - OnBeginDrag       - 即将开始拖动时在拖动对象上调用
IDragHandler - OnDrag            - 发生拖动时在拖动对象上调用
IEndDragHandler - OnEndDrag          - 拖动完成时在拖动对象上调用
IDropHandler - OnDrop            - 在拖动目标对象上调用

 

 

场景渲染方法
OnBecameVisible             当可见,当Mesh Renderer 在任何相机上可见时调用.
OnBecameInvisible             当不可见,当Mesh Renderer 在任何相机上不可见时调用.

 

 

结束阶段方法
OnDisable                但不可用,对象变为不可用或者附属游戏对象非激活状态时此函数被调用
OnDestroy               当销毁,当脚本销毁或附属的游戏对象被销毁时被调用
OnApplicationQuit            当程序结束,应用程序退出时条用

 

 

调试
两个都可以.但是print里面调用的就是Debug.Log()方法
如果你的类没有继承MonoBehaviour基类的话,是无法使用print的,但是可以用Debug.Log()方法
Debug.Log();       Debug.Log 可以在C#和脚本均可使用
print('ok');         print(仅能在脚本中使用)

调试方法2

定义共有变量,程序运行后在检测面板查看数据

调试方法3:使用VSTU
准备工作:
安装VSTU2013工具
在Unity项目面板中导入:VS2013Tool
调试步骤:
在可能出错的地方加断点
启动调试
在Unity中Play场景


常用类重点类
Component            组件 总结:Component类提供了查找(当前物体的先辈,后辈的)组件的功能
Transform            场景变换组件 提供了查找(父,根,子)变换组件,改变位置,角度,大小的功能
GameObject           游戏对象 操作,创建,查找游戏对象的功能
Object               所有类的父类
Time              时间管理类


Component
向前移动50米
this.transform.position = new Vector3(0, 0, 50);

将物体对象的颜色设置为红色
this.GetComponent<MeshRenderer>().material.color = Color.red;

获取游戏对象的所有组件
    var component_list = this.GetComponents<Component>();
    foreach (var item in component_list) {
    print(item.GetType());
}

获取后代的指定类型组件(从自身开始)
var houdai = this.GetComponentsInChildren<MeshRenderer>();
foreach (var item in houdai) {
    item.material.color = Color.yellow;
}


Transform
物体对于世界坐标系原点的位置
this.transform.position

物体相对于父物体轴心点的位置,子物体和父物体之间的距离
this.transform.localPosition

物体相对于父物体缩放比例 1 1 1
this.transform.localScale

物体于模型缩放比例(自身缩放比例 * 父物体缩放比例)
this.transform.lossyScale
例如:父物体localScale为3 子物体localScale为2 那么 localScale则为6

物体沿自身坐标系 y轴 旋转10度
this.transform.Rotate(0,10,0)


Transform 变换组件 提供了查找(父,根,子)变换组件,改变位置,角度,大小的功能
if (GUILayout.Button("向着自身反向移动")) {
    this.transform.Translate(0, 0, 1);
}
if (GUILayout.Button("向着世界坐标系反向移动")) {
    this.transform.Translate(0, 0, 1, Space.World);
}
if (GUILayout.Button("沿自身坐标系y轴 旋转10度")) {
    this.transform.Rotate(0, 10, 0, Space.Self);
}
if (GUILayout.Button("沿着世界坐标系y轴 旋转10度")) {
    this.transform.Rotate(0, 10, 0, Space.World);
}

RepeatButton:按住按钮不停响应
if (GUILayout.RepeatButton("围绕旋转")) {
    RotateAround(朝着三维坐标的0坐标,上下环绕目标,移动多少1米)
    this.transform.RotateAround(Vector3.zero, Vector3.forward,1);
}
if (GUILayout.Button("获取根物体变换组件")) {
    Transform root_transfrom = this.transform.root;
}
if (GUILayout.Button("获取父物体的变换组件")) {
    Transform parent_transfrom = this.transform.parent;
}
if (GUILayout.Button("基于世界坐标系:设置父物体,默认true")) {
    this.transform.SetParent(tf);
}
if (GUILayout.Button("基于自身坐标系:设置父物体")) {
    this.transform.SetParent(tf,false);
}

if (GUILayout.Button("找孩子")) {
  //找儿子
  this.transform.Find("子物体名称");
  //找孙子,写/后要确保路径不会发生变化,不然路径发生变法,代码就会报错,因为地址发生了变化
  this.transform.Find("子物体名称/子物体名称");
  //找重孙子
  this.transform.Find("子物体名称/子物体名称/子物体名称");
}

if (GUILayout.Button("根据索引获取子物体")) {
  int count = this.transform.childCount;
  for (int i = 0; i < count; i++) {
  this.transform.GetChild(i);
}
}


GameObject

/* GameObject 类
if (GUILayout.Button("添加光组件")) {
    //创建物体
    GameObject ao = new GameObject();
    //添加组件
    Light light = ao.AddComponent<Light>();
    //设置光的颜色
    light.color = Color.blue;
    //设置光的类型
    light.type = LightType.Point;

    //在场景根据名称查找物体(慎用,搜索量太大)
    //GameObject.Find("游戏对象名称");

    //获取所有使用该标签名称的物体(多个)
    GameObject[] alltag = GameObject.FindGameObjectsWithTag("hero");

    //获取使用该标签的物体(单个)
    GameObject tag = GameObject.FindWithTag("hero");


}
/*


Object
根据类型查找对象
Object.FindObjectOfType<hero>();

根据类型查找多个对象
Object.FindObjectOfType<hero>();

查找对象的名称
Object.name

销毁对象
Object.Destroy(game.object,5)    销毁一个对象5秒后移除

 

Time

time.delttime :            让物体在渲染帧下,保持均匀的速度,不会忽快忽慢(不受渲染内容多于少影响)
this.transform.Rotate(0, 100 * Time.deltaTime, 0);
Time.time :            游戏运行时间
Time.deltaTime:          受缩放影响的每帧经过的时间(默认0.2秒执行一次)
Time.unscaledDeltaTime      不受缩放影响的每帧经过时间
( 想实现暂停游戏的情况下,某些物体不受影响,可以使用这个属性 )

 

时间暂停/继续,快进,慢放
if (GUILayout.Button("暂停游戏")) {
  Time.timeScale = 0;
}
if (GUILayout.Button("继续游戏")) {
  Time.timeScale = 1;
}
if (GUILayout.Button("快进游戏")) {
  Time.timeScale = 10;
}
if (GUILayout.Button("慢放游戏")) {
  Time.timeScale = 1;
}


按秒修改一次时间
private Text txt;
private int second = 120;
private float nextTime = 1;
private float totalTime;

 

//按秒修改一次
//修改时间方法一:Time.time
private void Timer() {
    //判断当前的游戏时间是否 >= 自定义时间1;
    if (Time.time >= nextTime) {

      second--;
      txt.text = string.Format("{0:d2}:{1:d2}", second / 60, second % 60);
      //判断如果时间小于10,颜色变红
      if (second <= 10) {
        txt.color = Color.red;
      }

    //设置下一次修改时间( 间隔几秒执行一次 )
    nextTime = Time.time + 1;
    }
}

 

//修改时间方法二:Time.delta.Time
private void Timer2() {
  totalTime += Time.deltaTime;
  if (totalTime >= 1) {
    second--;
    txt.text = string.Format(" {0:d2}:{1:d2} ",second / 60 , second % 60 );
    totalTime = 0;
  }
}

 

//修改时间方法三:Invoke()
//每隔固定时间重复实行
private void Timer3() {

  second--;
  txt.text = string.Format(" {0:d2}:{1:d2} ", second / 60, second % 60);
  //如果当前时间 <= 0 ,就取消调用身上的()内方法
  if (second <= 0) {
  CancelInvoke("Timer3");
  //延迟执行
  //Invoke("方法名", 执行时间); invoke("Timer3",5) 五秒后执行
  }
}

 


public void Start() {
  txt = this.GetComponent<Text>();
  //重复调用( 方法名,第一次执行时间,每次执行间隔 )
  InvokeRepeating("Timer3", 1, 1);

}

 

 

 


预制件,可以跨场景sence使用
1:创建预制件

  将需要变成预制件的物体用鼠标拉到poject面板里
  此时,Hierarchy面板里的物体名称将被蓝色包围,此时的物体就变成了一个 预制件

2:预制件的用处
  用于快速修改物体的属性参数,即修改一个物体的参数,与它相同的预制件也一同变换,方便快速修改,降低开发时间

3:预制件的三大参数
  1:select 点击蓝色名称物体的select,会自动帮你找到预制件的位置
  2:reveit 撤销刚才对物体的操作,返还到预制件的物体属性参数状态
  3:apply 将某一实例的修改引用到所有实例

 

Unity4(老)动画组件animation
1:打开动画编辑器面板 ( Animation View )
window→Animation

2:点击需要添加动画的物体→Add Component→搜索添加Animation

3:点击创建好的动画编辑器面板→Create→需要什么就操作什么

4:时间轴
1:30    表示 1秒和30帧

5:最后把录制好的动画拖到物体组件Animation里

常用方法:
Play("动画名") 播放动画,
animaition.PlayQuened("动画名") 将()内的动画以队列方式播放,当第一个动画播放完才播放第二个
Animation["动画名"].speed = -1 倒着播放动画
Animation["动画名"].speed = 1 正着播放动画


//动画播放模式
once        点一次播放一次
loop        循环播放
pingpang      跟乒乓球似的,来回播放
clamp forever   播放最后一帧动画到永远

 

简单的创建一个门并添加开关门动画
#创建动画
1:创建一个GameObject物体
2:将这个物体放到门需要旋转的位置
3:将门拖到GameObject物体里成为子物体
4:给GameObject添加Animation
5:打开window→Animaition编辑器,添加动画位置
6:录制GameObject旋转动画
7:将保存的动画拖到GameObject物体里Animation选项右侧的动画添加区域
8:完成

#代码
using UnityEngine;

public class OpenTheDoor : MonoBehaviour {
private bool doorState = false;
private Animation animt;
private string anmt_name = "door";

public void Start() {
  animt = GetComponent<Animation>();
}

 

public void OnMouseDown(){

  //如果门的状态是true开门,就执行关门操作
  if (doorState) {
    animt[anmt_name].time = animt[anmt_name].length; 播放前,将动画时间转换为动画总长度
    animt[anmt_name].speed = -1;
  }
  //如果门的状态是false关门,就执行开门操作
  else {
    animt[anmt_name].speed = 1;
  }
  animt.Play(anmt_name);
  doorState = !doorState;
  }


}

 

查找距离角色最近的敌人
public Monster GetMonsterByMinNearest(Monster[] m_list) {
  //假设当前min时最近的敌人对象
  Monster min = m_list[0];

  //三维坐标判断,当前物体对象的坐标,假设对象的三维坐标
  float minNearest = Vector3.Distance(this.transform.position, min.transform.position);

    for (int i = 0; i < m_list.Length; i++) {

      //三维坐标判断,拿当前物体对象的三维坐标和所有物体对象三维坐标判断
      float newNearest = Vector3.Distance(this.transform.position, m_list[i].transform.position);

      //判断,如果假设的当前物体对象坐标 比 下一个对象的三维坐标近
      if (minNearest > newNearest) {
      //值变更
      min = m_list[i];
      minNearest = newNearest;
    }
  }
  return min;
}

 

获取键盘输入事件


Input.GetKey(KeyCode.A)        当通过指定按键名称被按下,按住时返回true
Input.GetKeyDown(KeyCode.A)    当按下指定键时,第一帧返回true
Input.GetKeyUp(KeyCode.A)      当按下指定键,抬起的那一帧返回true


获取鼠标事件
0 代表鼠标左键
1 代表鼠标右键
2 代表鼠标中键

Input.GetMouseButton(0)         当指定的鼠标按钮被按下时返回true
Input.GetMouseButtonDown(0)     当指定的鼠标按钮被按下的第一帧返回true
Input.GetMouseButtonUp(0)         当指定的鼠标按钮被释放的的第一帧返回true

 

//实现狙击枪开镜放大效果
Camera c;
private void Start() {
  c = this.GetComponent<Camera>();
}
public void Update() {
  if (Input.GetMouseButton(1) ) {
  c.fieldOfView = 5;
}
if (Input.GetMouseButtonUp(1)) {
  c.fieldOfView = 60;
}

 


三维数学
------左平滑移动可以用Lerp方法------
Mathf.Lerp(起点,终点,比例) Mathf.Lerp(camera.filedOfView,60,0.1f) 0.1f代表百分比


Mathf.Abs() 绝对值
Mathf.Lerp() 差值
Mathf.Pow() 求平方
Mathf.Sqrt() 开平方

实例代码:
public float[] count;
private int index;
private Camera cm;

private void Start() {
cm = this.GetComponent<Camera>();
}

private void Update() {
if (Input.GetMouseButtonDown(1)) {

//第一种写法
index = index < count.Length -1 ? index+1 : 0;
//第二种写法防止下标越界
index = index + 1 % count.Length;

}
cm.fieldOfView = Mathf.Lerp(cm.fieldOfView, count[index], 0.1f);
if (Mathf.Abs(cm.fieldOfView - count[index]) < 0.1f) {
cm.fieldOfView = count[index];
}

 


----------------------------------虚拟按键(InputManager)-----------------------------------
即输入管理器 Edit→Project Settings→Input
解释:使用脚本通过虚拟轴名称获取自定义按键的输入
作用:玩家可以在游戏启动时根据个人爱好对按键进行设置

------通用属性-----------
Name 虚拟按键名称
Descriptive Name 正向按钮描述信息
Descriptive Negative Name 负向按钮描述信息
Negative Button 绑定的真实按键名称1 负向按钮
Positive Button 绑定的真实按键名称2 正向按钮
Alt Negative Button 绑定的真实按键名称3 负向按钮
Alt Positive Button 绑定的真实按键名称4 正向按钮
Gravity 复位速度 不按任何按键的复位速度
Dead
Sensitivity 灵敏度 按下按键后的响应速度
Snap
Invent
Type 来源
Axis 绑定键位
Joy Num

 

 


-------------------------------------获取虚拟轴-----------------------------
返回值是true 或者false
bool i = Input.GetButton("虚拟轴名称");
bool i = Input.GetButtonDown("虚拟轴名称");
bool i = Input.GetButtonUp("虚拟轴名称");


//返回值是 -1 0 1
float value = Input.GetAxis("虚拟轴名称");
绑定键位a 和鼠标左键返回值(-1) 返回值为过度:0 → -0.5 → -1
不按返回0 0
绑定键位d 和右箭头,返回值(1) 返回值为过度:0 → 0.5 → 1


float value = Input.GetAxisRaw("虚拟轴名称");
绑定键位a 和鼠标左键返回值(-1) 直接显示返回值 -1
不按返回0 0
绑定键位d 和右箭头,返回值(1) 直接显示返回值 1

 

实例代码1:效果眩晕 不推荐
private void GetUserInput() {
//鼠标左右滑动
if (Input.GetAxis("Mouse X") > 0) {
this.transform.Rotate(0, 1, 0 * Time.deltaTime);
}else if (Input.GetAxis("Mouse X") < 0) {
this.transform.Rotate(0, -1, 0 * Time.deltaTime);

//鼠标上下移动
} else if (Input.GetAxis("Mouse Y") > 0) {
this.transform.Rotate(-1, 0, 0 * Time.deltaTime);
} else if (Input.GetAxis("Mouse Y") < 0) {
this.transform.Rotate(1, 0, 0 * Time.deltaTime);

//键盘左右ad移动
} else if (Input.GetAxis("Horizontal") < 0) {
this.transform.Translate(-1, 0, 0 * Time.deltaTime);
} else if (Input.GetAxis("Horizontal") > 0) {
this.transform.Translate(1, 0, 0 * Time.deltaTime);

//键盘上下ws移动
} else if (Input.GetAxis("Vertical") < 0) {
this.transform.Translate(0, 0, -1 * Time.deltaTime);
} else if (Input.GetAxis("Vertical") > 0) {
this.transform.Translate(0, 0, 1 * Time.deltaTime);

//鼠标滑轮上下滑动
} else if (Input.GetAxis("Mouse ScrollWheel") >0) {
if (c.fieldOfView < 60) {
c.fieldOfView = Mathf.Lerp(c.fieldOfView,60,0.1f);
}
} else if (Input.GetAxis("Mouse ScrollWheel") < 0) {
if (c.fieldOfView > 15) {
c.fieldOfView = Mathf.Lerp(c.fieldOfView, 15, 0.1f);
}
}

--------------------------------实例代码2,实现鼠标上下左右移动--:----------------------------------------
public float rotateSpeed = 2;

平稳旋转镜头,推荐
private void FixedUpdate() {

//获取虚拟按键X,Y
float x = Input.GetAxis("Mouse X");
float y = Input.GetAxis("Mouse Y");
if (x != 0 || y != 0) {
Rotate(x, y);
}

}

private void Rotate( float x, float y) {
x *= rotateSpeed;
y *= rotateSpeed;

//将虚拟按键的对应真实按键X,Y传入视角坐标
this.transform.Rotate(-y, 0, 0);
//左右旋转,需要沿世界坐标系的Y轴旋转,这样不会晕
this.transform.Rotate(0, x, 0, Space.World);
}

 

-----------------------------------实例代码3:实现2D视角前后左右移动------------------------

private void Update() {
float leftAndRight = Input.GetAxis("Horizontal");
float upAndDown = Input.GetAxis("Vertical");
if (leftAndRight != 0 || upAndDown != 0) {
Rotate_2(leftAndRight, upAndDown);
}
}

private void Rotate_2( float leftAndRight, float upAndDown) {
leftAndRight *= rotateSpeed * Time.deltaTime;
upAndDown *= rotateSpeed * Time.deltaTime;
this.transform.Translate(-leftAndRight, 0, 0);
this.transform.Translate(0, 0, -upAndDown);
}

 

 

----------------------------------3D数学-----------------------------------

---------------------求向量的模长---------------------
Vector3 v = this.transform.position;

//计算模长方法1
float m1 = Mathf.Sqrt( Mathf.Pow(v.x,2) + Mathf.Pow(v.y,2) + Mathf.Pow(v.z,2) + );

//计算模长方法2(Uinty3D 提供的内置API)
float m2 = v.magnitude;

//计算模长方法3
float m3 = Vector3.Distance(Vector3.Zero,v);

//在视图内显示从世界坐标零点位置到 物体的位置的一根线
Debug.DrawLine(Vector3.zero.v);

 

--------------------求向量的方向--------------------
几何意义:将该向量拉长或者缩短,使模长等于1
//Uinty API(获取显得的方向 归一化 标准化) 计算单位向量
v.normalized;

 

-------------------------------------------向量的计算-------------------------

----------------------向量相减------------------
public Transtion T1
public Transtion T2
public Transtion T3

Vector3 v3 = T1.position - T2.position
//方向:指向(谁减谁,方向就指向谁)
//大小:两点间距
注意:实际位置要平移到坐标原点


-------向量的作用---------------------
向量有什么用???
比如说:敌人向你开枪,敌人得有一个指向方向
例如:让敌人瞄准主角的头部射击
公式:用主角的头部坐标 - 敌人枪口的坐标


-----------简单小案例--------------沿着指向的方向移动
T3.Translate(v3.normalized); 加normalized表示,避免两个物体间距对速度的影响,所以只获取距离

 

----------------向量相加---------------
等于各分量相加和
公式:[x1,y1,z1] +[x2,y2,z2]=[x1+x2,y1+y2,z1+z2]
几何意义:向量a与向量b相加,平移使b的初始点与a的终点重合,
结果为以a的始点为始点,以b的终点为终点的向量
引用价值:物体朝着方向移动

----------------------------------------------三角函数------------------------------
---关于三角函数的理解---
对于一个角,把它放入一个直角三角形中,
则有一条他的对边,一条斜边,一个临边,
正弦 是对边长 / 斜边,
余弦 是临边 / 斜边,
正切 是对边 / 临边,
余切 是临边 / 对边,

 

---三角函数公式:( 什么时候用三角函数? 根据一边一角,计算另外一边长 )
正弦 sin x = a / c;
什么是正弦?
正弦(sine),任意一锐角∠A的对边与斜边的比叫做∠A的正弦,
记作sinA(由英语sine一词简写得来),即sinA=∠A的对边/斜边。


余弦 cos x = b / c;
余弦(cosine)在Rt△ABC(直角三角形)中,∠C=90°,∠A的余弦是它的邻边比三角形的斜边,即cosA=b/c,也可写为cosa=AC/AB。余弦函数:f(x)=cosx(x∈R)。

正切 tan x = a / b
正切 (tan), 在Rt△ABC(直角三角形)中,∠C=90°,AB是∠C的对边c,BC是∠A的对边a,AC是∠B的对边b,正切函数就是tanB=b/a,即tanB=AC/BC。


API内置函数写法:(radian 代表弧度 )
Mathf.Sin(float radian)
Mathf.Cos(float radian)
Mathf.Tan(float radian)

 

----反三角函数公式( 什么时候用反三角函数? 根据两边长,计算角度 )
反正弦 arcsin a / c = x;


反余弦 arccos b / c = x;
反正切 arctan a / c = x;

API内置函数写法:
Mathf.Asin(float radian)
Mathf.Acos(float radian)
Mathf.Atan(float radian)

 

 

-------------角度转弧度----------------
弧度 = 角度数 * PI / 180

float jiaodu = 60;
//写法一
float hudu = jiaodu *Mathf.PI / 180;
//写法二
float hudu = jiaodu * Mathf.Deg2Rad;


---------------弧度转角度-----------------
角度 = 弧度数 * 180 / PI

float hudu = 2;
//写法一
float jiaodu = hudu * 180 / Mathf.PI;
//写法二
float jiaodu = hudu * Mathf.Rad2Deg;


--------------已知角度X,边长b---------------------
求:边长a
公式:a = tan x * b
float x = 50,b = 20
float a = Mathf.Tan(x * Mathf.Deg2Rad) * b

 

-------------已知边长a,边长b------------------
求:角度 z
公式:z = arc tan a / b
float z = Mathf.Atan( a / b ) * Mathf.Rad2Deg;


-------------从自身坐标转换为 世界坐标 方法--------------------
Vector3 worldPoint = this.transform.TransformPoint(0,0,10)

 

 

--------------------------------点乘----------------------------
又称 点积 或 内积
公式:各分量乘积和
[x1,y1,z1] · [x2,y2,z2] = x1x2 + y1y2 + z1z2
几何意义: a · b = |a| · |b| cos <a,b>
两个向量的单位向量相乘后乘以二者夹角的余弦值
API:
float dot = Vector3.Dot(va,vab)

结果与角度的关系:
对于标准化过的向量

方向完全相同,点成结果为1
完全相反,点乘结果为-1
互相垂直结果为0

0度(1)
30°(0.866)
45°(0.7071)
60(0.5)
90(0)
120°(-0.5)
135°(-0.7071)
150°(-0.866)
180°(-1)

----------------------计算两个向量的夹角------------------


-----------------点乘----------------
1:计算两个向量夹角的cos值
float dot = Vector3.Dot(t1.position.normalized,t2.position.normalized)
2:计算夹角
angle = Mathf.Acos(dot) * Mathf.Rad2Deg;
3:判断如果向量夹角大于60度,则...
if angle > 60)


第二种写法:
1:计算两个向量夹角的cos值
float dot = Cector3.Dot(t1.position.normalized,t2.position.normalized)

2:直接拿cos值做判断
if(dot < 0.5f)

 

-----------------叉乘--------------------
计算叉乘:
Vector3 cross = Vector3.Cross(t1.position,t2.position)
计算一圈夹角
if(cross.y < 0){
angle = 360 - angle;
}

 

------------------------------------欧拉角 this.transfrom.eulerAngles---------------------
什么是欧拉角?
使用三个角度来保存范围
X与Z轴沿自身坐标系旋转,Y轴沿世界坐标系旋转
API:
Vector3 euler = this.transfrom.eulerAngles;

为了保证任意范围都独一无二
Unity限制了角度范围
X旋转 -90° - 90°
Y和Z 0°-360°


----欧拉角与向量的区别----
向量:
Vector3 pos = this.transfrom.position;
位置:有方向(从世界原点指向当前位置)
大小(当前位置到世界原点间距)
向量的x,y,z,表示各个轴向上的有向位移

欧拉角:
Vector3 euler = this.transfrom.eulerAngles;
注意:欧拉角没有方向,大小的概念
因为三维向量,包含x,y,z,所以在Unity中,欧拉角的数据类型为Vector
欧拉角的x,y,z,表示各个轴向上的旋转角度

通过设置欧拉角旋转物体(各分量相加, 欧拉角的x增加1度)
this.transfrom.eulerAngles += new Vector3(1,0,0);

欧拉角的 Y 增加1度
this.transfrom.eulerAngles += Vector3.Up();

欧拉角的 Z 增加1度
this.transfrom.eulerAngles += Vector3.forword();


优点:好用简单
缺点
------万向节死锁---
物体沿X轴旋转正负90度,自身坐标系Z轴与世界坐标系Y轴将重合
此时在沿Y OR Z 旋转时,将失去一个自由度
在万向节死锁情况下,规定沿Y轴完成绕竖直轴的全部旋转,
即此时Z轴旋转为0


-----------------------------四元数------------------------

this.transform.Rotate() 返回值就是一个四元数
优点:避免万向节死锁

什么是四元数
Quaternion 在3D图形学中代表 旋转
由一个三维向量(X,Y,Z) 和 一个标量(W)组成
旋转轴为V,弧度为0,如果使用四元数表示,则四各分量为:
x = sin(0/2) * V.x
y = sin(0 / 2) * V.y
z = sin(0 / 2 ) * V.z
w = cos( 0 / 2)

X,Y,Z,W的取值范围是 -1到1
API


实例代码:

旋转轴
Vector3 axis = Vector3.up;
旋转弧度
float rad = 50 * Mathf.Deg2Rad;

创建四元数
Quaternion qt = new Quaternion();
qt.x = Mathf.Sin(rad / 2) * axis.x;
qt.y = Mathf.Sin(rad / 2 ) * axis.y;
qt.z = Mathf.Sin(rad / 2 )* axis.z;
qt.w = Mathf.Cos(rad / 2 );

将结果赋值给移动组件的旋转rotation
this.transform.rotation = qt;

当前,Uinty早就给你做好了方法,不需要上边的复杂写法

想要移动物体,直接写:
this.transform.rotation *= Quaternion.Euler(0,50,0) 结果就向y轴旋转50度了


优点:避免万向节死锁
缺点:难于使用,不建议的单独修改某个数值
存在不合法的四元数


---实现输出显示目标物体前方10米30度方向的向量线------
public Verctor3 v

private void Update(){
根据当前物体的旋转而旋转
v = this.transform.rotation * new Vector3(0,0,10);
沿Y轴旋转30度
v = Quaternion.Euler(0,30,0) * v;
移动到当前物体位置
this.trannsform.position + v;

}


---实现小功能( 根据怪物和主角之间的间距,判断角色是否在怪物的攻击范围 )

float jianju v.Distance( hero.position,moster.postion );
if( jianju <10 ){

}

 

------------------------------检测游戏对象的半径 和 显示 游戏对象的向量------------------------
private GameObject hero; //游戏对象
public Transform heroTF; //组件
private float radius; //半径
private Vector3 left, right;
public void Start() {
//查找游戏对象
hero = GameObject.Find("hero");
heroTF = hero.transform;
radius = hero.GetComponent<CapsuleCollider>().radius;
}

public void Update() {
//显示代码附属物体 → hero游戏对象的向量
Jiance();
}


//计算切点
private void jsqd() {
//玩家的到炸弹的向量()
Vector3 wjTbzd = this.transform.position - hero.transform.position;
//玩家到物体半径的向量
Vector3 wjTbj = wjTbzd.normalized * radius;
//计算夹角
float angle = Mathf.Acos(radius / wjTbzd.magnitude) * Mathf.Rad2Deg;
//旋转
left = heroTF.position+ Quaternion.Euler(0, -angle, 0) * wjTbj;
right = heroTF.position + Quaternion.Euler(0, angle, 0) * wjTbj;
}

public void Jiance() {
jsqd();
//画线
Debug.DrawLine(this.transform.position, left, Color.green);
Debug.DrawLine(this.transform.position, right, Color.green);
Debug.DrawLine(this.transform.position, hero.transform.position, Color.red);

}


----------------------------------Vector3 三维向量-------------------------
Vector3.Up
Vector3.Down
Vector3.Left
Vector3.Right
Vector3.Zero
Vector3.X
Vector3.Y

//移动
Vector3.MoveTowards(移动前位置,移动后位置,速度) 匀速移动,可以到达目标点
Vector3.Lero(移动前,移动后,速度) 按比例移动,越接近越慢,无限接近物体,不可到达
Vector3.LerpUnclamped(起点,终点,anmc.Evaluate(X)) 按比例移动,不限制,可以超过设定的终点,有回弹效果 x记得 *Time.DeltaTime
public AnimationCurve anmc; 曲线,可以设定曲线后,在放到移动参数中,那么移动将按照曲线设定移动

//常用
Vector3.magnitude() 获取向量长度
Vector3.Distance(a,b) 返回a和b之间的距离
Vector3.Normalized 将向量长度归一
Vector3.sqrMagnitude 返回该向量的长度平方
Vector3.Angle(从哪,到哪) 返回由哪到哪的角度 计算角度(方法内部自动归一向量) ---重点---
Vector3.Normalize() 将向量长度设置为1
Vector3.OrthoNormalize() 使向量归一且彼此相互垂直 获取垂直向量

Vector3.ClapMagnitude 返回向量的长度,最大不超过参数的值
Vector3.Cross 两个相连的交叉积成
Vector3.Dot 两个向量的点乘积
Vector3.Project(Vector3 a , Vector3 b) 投影参数1到参数2(投影一个向量到另一个向量)
Vector3.Reflect() 沿着法线反射向量,结果为入射线的放射线向量


------总结------
1欧拉角 转换 四元数
Quaternion.Euler(欧拉角或坐标或向量)

2四元数 转换 欧拉角
Quaternion qt = this.transform.rotation
Vector3 euler = qt.eulerAngles;

3 轴 / 角的旋转
this.tranform.rotation = Quaternion.AngleAxis(50,Vector3.Up)

4注视旋转 Z轴(3D) 指向一个方向(参数向量)
public Transfrom tf;
Vector3 dir = tf.position - this.transform.position
this.transform.rotation = Quaternion.LookRotation( dir )

5注视旋转2(僵硬快速旋转)
this.transform.LookAt(tf)

6注视旋转3(自然旋转)
Quaternion dir = Quaternion.LookRotation(tf.position - this.transform.position)
//插值旋转Lerp
this.transform.rotation = Quaternion.lerp(this.transform.rotation,dir,0.1f)

//匀速旋转Quaternion.RotateTowards
this.transform.rotation = Quaternion.RotateTowards(this.transform.rotation,dir,0.1f)

//判断当前旋转角度 与 目标旋转角度接近时,就表两个旋转角度相等
float angle = Quaternion.Angle(this.transform.rotation , tf.transform.rotation);
if(angle < 0.1f){
this.transform.rotation = dir;
}

7X轴方向注视旋转(2D)
//一帧转
Quaternion qt = Quaternion dir =QuaternionFormToRotation(Vector3.right,tf.position - this.transform.position);
this.transform.rotation = qt;

 

 

---------------------按照输入的wsad方向移动旋转------------------------
private float MoveSpeed = 5;
private float RotateSpeed = 2.5f;

private void Update() {
//获取虚拟按键wsad
float LandR = Input.GetAxis("Horizontal");
float UandD = Input.GetAxis("Vertical");
//判断不等0才调用方法,等于0就是没有移动
if (LandR != 0 || UandD != 0) {
Rotate(LandR, UandD);
}

}

private void Rotate(float LandR,float UandD) {
//创建一个向量
Quaternion dir = Quaternion.LookRotation(new Vector3( LandR, 0, UandD));
//匀速旋转
this.transform.rotation = Quaternion.Lerp(this.transform.rotation, dir, Time.deltaTime * RotateSpeed);
//匀速移动
this.transform.Translate(0, 0, Time.deltaTime * MoveSpeed);
}

 

-------------------------------------------------坐标系 和 坐标系之间的转换-----------------------------
-------------------Local Space → World Space 自身坐标转换世界坐标-----------
this.transform.forward 在世界坐标系中表示物体 正前方
this.transform.right 正右方 正左方 -right
thistransform.up 正上方 正下方-up

this.transform.TransformPoint 转换点 受变换组件 位置,旋转,缩放影响
this.transform.TransformDirection 转换方向,受变换组件旋转影响
this.transform.TransformVector 转换向量,受变换组件旋转和缩放影响

 

-------------World Space → Local Space(世界转自身)-----------------------
this.transform.InverseTransformPoint 转换点 受变换组件 位置,旋转,缩放影响
this.transform.InverseTransformDirection 转换方向,受变换组件旋转影响
this.transform.InverseTransformVector 转换向量,受变换组件旋转和缩放影响

 

-------------WORLD sPACE ← → Screen Space 世界转屏幕,屏幕转世界坐标系------
Camera.main.WorldToScreenPoint 将点从世界坐标系转换到屏幕坐标系中
Camera.main.ScreenToWorldPoint 将点从屏幕坐标系转换到世界坐标系


------------World Space ← → Vuewport Space 世界坐标到屏幕坐标系转换到视口坐标系-
Camera.main.WorldToViewportPoint 将点从世界转视口坐标系
Camera.main.ViewportToWorldPoint 将点从视口转换到世界坐标系

 


--------------------------------===物理引擎---------------------------------2020年7月29日13点43分

---------刚体 Add Copponet →Rigidbody---
添加此组件后,当前物体就具有了 物理特性
比如说,在天空中的物体加上这个刚体,游戏运行后,
物体会落下

Rigidbody属性设置
Mass0.0000001,1000000000 代表物体的质量重量,根据现实大小设定
Drag阻力 空气阻力,摩擦力,极大时可使物体停止运动,通常砖头0.001,羽毛10
Angular Drag 角阻力 当受扭力旋转式物体受到的空气阻力,0表示没有空气阻力.极大时物体停止旋转
Use Gravity 使用重力 若激活,则物体受重力影响
Is Kinematic 是否时运动学 若激活,该物体不再受物理引擎控制,而只能通过变换组件来操作
Interpllate 插值 用于缓解刚体运动时的抖动,无None 不应用插值
Interpolate 基于上一帧的变换来平滑本帧变换
Extraolate 基于下一帧的预估变换来平滑本帧变换


Collision Detection 碰撞检测模式,快速移动的刚体在碰撞时有可能互相穿透,可以设置碰撞检测率,但频率越高对物体引擎性能消耗越大
Discrete不连续 不连续碰撞检测,适用于普通碰撞(默认)
Continuous连续 连续碰撞检测
Continuous Dynamic 连续动态碰撞检测,适用于告诉物体

Constraints 对刚体运动的约束
冻结位置Freeze Position 刚体在世界中沿所选XYZ轴的移动,将无效
冻结旋转Freeze Rotation 刚体在世界中沿所选的XYZ轴的旋转,将无效

 


-------------碰撞器collider-------------
手游适用 Box Collider
可通过Edit Collider 在scence面板面积碰撞器面积大小
不同的碰撞器,显示的效果不同,可选择适合自己需要加碰撞器的物体的心态而定

2D碰撞器:
Box Collider2D 2D游戏使用
Circle Collider2D 2D圆形碰撞器
Edge Collider2D 2D边缘碰撞器
Polygon Collider 2D 2D多边形碰撞器


3D碰撞器
Box Collider 盒子碰撞器
Capsule Collider 胶囊碰撞器
Mesh Collider 材质点线面碰撞器,根据物体的材质所有的面来检测碰撞 过于消耗性能
Sphere Collider 球形碰撞器
Terrain Collider 地形碰撞器
Wheel Collider 车轮碰撞器
World Particle Collider 世界粒子碰撞器

碰撞条件:
两者具有碰撞组件
运动的物体具有刚体组件

----------碰撞三阶段,----------

当进入碰撞时执行
Void OnCollisionEnter(Collision collOther)
collOther.cllider.GetConpontn<?>() 获取对方碰撞器组件
collOther.contacts[0] 获取第一个接触点
collOther.point 接触点的世界坐标
collOther.normal 接触面的法线


当碰撞器与刚体接触时每帧执行
Void OnCollisionStay(Collision collOther)

当停止碰撞时执行
Void OnCollisionExit(Collision collOther)

 

碰撞器组件下 Is Trigger 若被勾选 则效果为没有碰撞效果

 

-------------触发三阶段-----------------
当Collider碰撞器进入触发器时执行
Void OnTriggerEnter(Collider c) 就是对方碰撞器组件

当碰撞体与触发器接触时每帧执行
Void OnTriggerStay(Collider c)


当停止触发时执行
Void OnTriggerExit(Collider c)


---------------------------------小知识---------------------------------
如果一个物体添加了碰撞器Collider
然后把里面的Is Trigger 勾上,就变成了触发器,可以触发事件
把碰撞器的范围设置成攻击范围
就可以检测谁进入了攻击范围,并进行攻击
如果想给角色区分脑袋和身体的伤害区别
可以给各个部位添加碰撞器,勾选Is Trigger即可


-----------------检测--------------------------------------
由于3D射击游戏射击速度过快导致无法每帧检测到子弹
所以有了新的解决方案,---------射线检测----------
RaycastHit hit;
public Vector targetPoint;
public LayerMask lm;
private float MoveSpeed = 50;

private void Start(){

//Physics.Raycast(起点,发射的方向,受击物体信息,距离,?层,)
bool p = Physics.Raycast(this.transform.position,this.transform.forward,out hit,100,lm)
if(p == true){
targetPoint = hit.point;
}else{
//子弹就飞到我的坐标往前100米
targetPoint = this.transform.position + this.transform.forward * 100
}

}

private voidUpate(){
//平滑移动 (起点,终点,速度)
this.transform.position = Vector3.moveTowards(this.transform.position,targetPoint,MoveSpeed *Time.DeltaTime);
//判断,如果我当前的坐标 - 目标坐标 的距离 的大小距离小于0.1f,
if( (this.transform.position - targetPoint).sqrMagnitude < 0.1f ){
//就表示子弹触及了目标点,击中了
//击中了销毁子弹
Destory(this.gameObject)
}else{
//没有击中
}
}

--------------------------------------UGUI--------------------------------------------

---------------------------画布2020年7月30日---------------------
层级关系
在同一画布中,图片谁在下,谁就在最上层,就覆盖谁

在不同画布中,谁的Sort Order值越大,谁覆盖谁,谁就在最上层

画布模式
1:Screen Space - Overlay 屏幕坐标系覆盖模式2D 在此模式下,可以用世界坐标设置物体的位置
2:Screen Space - Camera 屏幕坐标系摄像机模式2D 需要提供一个摄像机,画布适应摄像机远近大小变化
Render Camera 渲染摄像机
Plane Distace 平面与摄像机的距离
Sorting Layer 排序层,通过Eidt→Project Settings→Tags and Layers 调整Canvas渲染顺序

3:World Space 世界空间3D模式,画布渲染与世界空间,与场景中其他3D物体特性相同

 

如果选择摄像机模式(为了让UI在3D物体前,一般适用于游戏选项菜单设置界面)
1UI摄像机的深度值应大于主摄像机
2UI摄像机Clear Flags 选择Depth only 仅深度
3:UI摄像机Culling Masjk 选择UI 仅显示UI
4主摄像机把UI取消掉,不看UI
5:UI摄像机Proojectction 选择Orthogrphic2D模式
6UI摄像机要POSITION X坐标输入10000 远离主摄像机 这样互不干扰


------------------锚点------------------------
将画布背景图片的锚点分布到四角后,图片就会自适应分辨率

获取UI宽度(只读)
方法1:
RectTransform rtf = GetComponent<RectTransform>();
方法2:
RectTransform rtf = this.transform as RectTransform;

//获取自身轴心点相对于锚点的位置(pos)
rtf.anchoredPosition3D

//获取/设置锚点
rtf.anchorMin

//获取UI宽度()
rtf.rect.width
//获取高度
rtf.rect.height

//设置UI宽度
rtf.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal,200);

//设置UI高度
rtf.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical,200);


//当锚点不分开时,数值可以理解为UI宽高
//物体大小 - 锚点间距
rtf.sizeDelta;


//UGUI常用功能类

RectTransformUtility

 

--------------Button 按钮-----------------

 

 

 

 

-----text----------勾选Rich Text才有效
富文本语法
<b>粗体</b>
<i>斜体</i>
<size =14>字号</size>
<color=red>颜色</color>

 

------------Toggle复选框--------------
适合做记住账号
Is On 代表选没选中


------------Slider滑动条----------------
Value 代表当前值
Min Value 最小值
Max Value 最大值
样的一个Slider里会包含
Background
Fill Area
Handle Slide Area
三个部分
其中Handle Slide Area就是滑块,血条不需要滑块,因此要将它删掉。
我以为将滑块删掉就万事大吉不用改了,谁知却遇到一个问题。
Value为0的时候,血条在表现上还有残留的血量:
Value为1的时候,血量却还没填满整个血条:
怎么办?
将Fill Area及其孩子Fill的Left和Right都调成0才行,这样问题就解决了。

适合做HP MP血条
记得制作好血条后 将Interactable 取消勾选 ,
取消交互效果,不然在游戏中可以自己拖动血条


------------------Scrollbar滑动条进度条-------------------
适合做背包下滑

 


--------------------Dropdown下拉菜单-----------------

---------------------Scroll Rect实现滚动效果------------------------
Content:想要滚动的内容
Horizontal:横向滚动,打勾即允许
Vertical:纵向滚动,打勾即允许
Movement Type:滚动类型
Unrestricted:无限制的滚动,无回滚
Elastic:有限制的滚动,有回滚
Clamped:有限制的回滚,无回滚
Elasticity:回滚系数,数值越大弹性越小
Inertia:惯性
Deceleration Rate:减速率
Scroll Sensitivity:滚动的灵敏度
Horizontal Scrollbar:横向滚动条
Vertical Scrollbar:纵向滚动条


-----------------------------------Scrollbar 滚动条-----------------------

 

--------------------------------TWeen插件,集成移动,旋转,缩放,震动,晃动等功能------------

if (GUILayout.RepeatButton("点击移动")) {
//移动(从哪个游戏对象,移动到哪个位置?,多长时间到达?>)
iTween.MoveTo(KnowTF.gameObject, TarTF.position, 2);
}
if (GUILayout.RepeatButton("注视旋转")) {
//移动(从哪个游戏对象,移动到哪个位置?,多长时间到达?>)
iTween.LookTo(KnowTF.gameObject, TarTF.position,3);
}
if (GUILayout.RepeatButton("震动")) {
//移动(从哪个游戏对象,移动到哪个位置?,多长时间到达?>)
iTween.ShakePosition(KnowTF.gameObject, TarTF.position, 3);
}
if (GUILayout.RepeatButton("晃动")) {
//移动(从哪个游戏对象,移动到哪个位置?,多长时间到达?>)
iTween.PunchPosition(TarTF.gameObject, TarTF.position,3);
}
if (GUILayout.RepeatButton("物体旋转")) {
//移动(从哪个游戏对象,移动到哪个位置?,多长时间到达?>)
iTween.RotateTo(KnowTF.gameObject, TarTF.position, 3);
}
if (GUILayout.RepeatButton("颜色渐变")) {
//移动(从哪个游戏对象,移动到哪个位置?,多长时间到达?>)
iTween.ColorTo(KnowTF.gameObject, Color.green,3);
}
if (GUILayout.RepeatButton("物体缩放")) {
//移动(从哪个游戏对象,移动到哪个位置?,多长时间到达?>)
iTween.ScaleTo(TarTF.gameObject,new Vector3(5,0,0),3);
}

 

posted @   伊凡晴天  阅读(232)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示