1.常用组件
组件 | 作用 |
---|---|
Transform | 存储个处理游戏对象的位置、旋转和缩放 |
Mesh Filter | 显示网格 |
Rigidbody | 刚体,使物体能在物理控制下运动 |
Collider | 碰撞器,和刚体一起来是游戏对象发生碰撞 |
Renderer | 渲染器,使物体在屏幕上显示出来 |
Audio Source | 音频源,在场景中可以播放音频剪辑 |
Animation | 播放指定的动画剪辑 |
Animator | 通过动画控制器设置角色上的行为 |
Script | 定义自定义功能和各种交互操作 |
Particle System | 用于创作烟雾,气流,火焰,瀑布,喷泉等效果 |
2.常用周期事件
事件方法 | 说明 |
---|---|
Awake | 唤醒事件,在脚本实例被创建时调用,只执行一次 |
OnEnable | 启用事件,在每次激活脚本时调用 |
Start | 开始事件,用于游戏对象或游戏场景的初始化,在场景被加载时调用,只执行一次 |
FixedUpdate | 固定更新事件,0.02秒执行一次。所有物理组件相关的更新都在这个事件中处理。 |
Update | 更新事件,每帧执行一次 |
LateUpdate | 延迟更新,每帧执行一次,在Update事件之后执行。和相机有关的更新一般都放在这。 |
OnGUI | 用来绘制交互界面,每帧会调用多次 |
OnDisable | 禁用事件,取消脚本的激活状态后调用 |
OnDestroy | 当前脚本被销毁时调用 |
如下输出,各函数的调用次数。
3.向量
二维向量Vector2 | 方法 |
---|---|
down | Vector2(0,-1) |
left | Vector2(-1,0) |
one | Vector2(1,1) |
right | Vector2(1,0) |
up | Vector2(0,1) |
zero | Vector2(0,0) |
magnitude | 返回向量长度 |
normalized | 单位化向量,长度变为 1,方向不变 |
//静态变量.类名来调用print(Vector2.down);print(Vector2.up);print(Vector2.left);print(Vector2.right);print(Vector2.zero);print(Vector2.one);//创建向量Vector2 a = new Vector2(4,5);Vector2 b = new Vector2(1,3);//返回向量长度print(a.magnitude);print(b.magnitude);//返回单位化向量,原向量不变print(a.normalized);print(a.x + "," + a.y);print(b.normalized);print(b.x + "," +b.y);//对向量进行单位化,原向量改变a.Normalize();print(a.x + "," + a.y);//输出两个向量之间的距离print(Vector2.Distance(a, b));//输出两向量之间的角度print(Vector2.Angle(a, b));
三维向量Vector3 | 方法 |
---|---|
back | Vector3(0,0,-1) |
down | Vector3(0,0,-1) |
forward | Vector3(0,0,1) |
left | Vector3(-1,0,0) |
one | Vector3(1,1,1) |
right | Vector3(1,0,0) |
up | Vector3(0,1,0) |
zero | Vector3(0,0,0) |
Angle | 两向量的夹角 |
Cross | 叉乘,满足左手法则,结果为一个向量 |
Dot | 点乘,结果为一个值 |
MoveTowards | 由当前位置匀速移动到目标位置 |
Slerp | 对长度和角度进行插值,用于对象的转向,比较平滑 |
+,-,*,/,!=,== | 相关运算 |
4.键盘和鼠标输入
相关方法 | 说明 |
---|---|
Input.GetKey() | 按下某键,持续返回true |
Input.GetKeyDown | 按下某键的一瞬间,返回true |
Input.GetKeyUp | 松开某键的一瞬间,返回true |
Input.GetMouseButton(0) | 持续检测是否按鼠标左键(针对鼠标左中右键,三个方法同) |
Input.GetMouseButtonDown(1) | 检测是否按下了右键,检测一次 |
Input.GetMouseButtonUp(2) | 检测是否按下了鼠标中键[参数左键(0),右键(1),中键(2) ] |
Input.GetButton | 持续检测 |
Input.GetButtonDown | 检测是否按下,检测一次 |
Input.GetButtonUp | 检测是否松开,检测一次 |
Input.GetAxis | 获取虚拟轴,返回-1到1之间的浮点数,有渐变效果 |
Input.GetAxisRow | 返回-1,0,1三个值,没有渐变效果 |
OnMouseDrag | 当鼠标拖动(获取鼠标的行为事件,不针对左中右键,下同) |
OnMuseDown | 当鼠标按下 |
OnMouseUp | 当鼠标抬起 |
OnMouseEnter | 当鼠标进入 |
OnMuseExit | 当鼠标退出 |
OnMuseOver | 当鼠标经过 |
//获取键盘的输入,检测按下和松开。if(Input.GetKey(KeyCode.A))print("GetKey:A");if(Input.GetKeyDown(KeyCode.A))print("GetkeyDown:A");if(Input.GetKeyUp(KeyCode.A))print("GetKeyUp:A");//检测鼠标右键状态if (Input.GetMouseButton(1))print("Mouse right");if (Input.GetMouseButtonDown(1))print("Mouse right down");if (Input.GetMouseButtonUp(1))print("Mouse right up");
获取按钮和虚拟轴:
通过Edit–>Project Setting–>Input Manager–>Axes打开,可以查看相关配置信息。如Fire1的配置如下。按下鼠标左键(Mouse 0)和按下左边的Ctrl都会响应。
//检测按钮Fire1状态if (Input.GetButton("Fire1"))print("Button Fire1");if (Input.GetButtonDown("Fire1"))print("Button Fire1 Down");
获取虚拟轴,按下左右的方向键或者a、d键,输入虚拟轴的值。
//获取虚拟轴的状态//一般用来控制物体的左右,前后移动或者旋转float h1 = Input.GetAxis("Horizontal");print(h1);float h2= Input.GetAxisRaw("Horizontal");print(h2);
改变一个游戏对象的颜色。
private void OnMouseEnter(){gameObject.GetComponent<MeshRenderer>().material.color = Color.red;}private void OnMouseExit(){gameObject.GetComponent<MeshRenderer>().material.color = Color.white;}
5.Time类及其成员变量
通过Time类可以获取和时间有光的信息,用来计算帧速率,调整时间流逝的速度等。
成员变量 | 功能 |
---|---|
Time | 游戏开始到现在的时间( 秒) |
deltaTime | 上一帧消耗的时间 |
fixedTime | 最近FixedUpdate已经开始的时间,该时间从游戏开始计算 |
fixedDeltaTime | 物理引擎和FixedUpdate更新时间间隔 |
timeScale | 时间流逝速度比例。可以用来制作慢动作特效 |
frameCount | 已渲染的帧总数 |
smoothDeltaTime | Time.deltaTime的平滑淡出 |
timeSinceLevelLoad | 此帧的开始时间,从关卡加载完成开始计算 |
maximumDeltaTime | 一帧的最大耗费时间 |
realtimeSinceStartup | 游戏开始到现在经历的真实时间,该时间不会受timeScale的影响 |
captureFramerate | 固定帧设置 |
print("Time.time:" + Time.time);print("Time.deltaTime:" + Time.deltaTime);print("Time.fixedDeltaTime:" + Time.fixedDeltaTime);print("Time.fixedTime:" + Time.fixedTime);print("Time.timeScale:" + Time.timeScale);
//通过计时器来控制Cube的状态private float time = 3.0f;//运行时在Unity面板上设置值public float speed;public float rotaeSpeed;private void Update(){time -= Time.deltaTime;if(time<=0){time = 3.0f;//处理逻辑,该属性取反,禁用时,不渲染。GetComponent<MeshRenderer>().enabled = !GetComponent<MeshRenderer>().enabled;}//控制物体每秒移动多少米transform.Translate(Vector3.right * Time.deltaTime*speed);//控制物体每秒旋转的角度transform.Rotate(Vector3.up * Time.deltaTime * rotaeSpeed);//通过按键来控制时间流速的大小if (Input.GetKeyDown(KeyCode.Q))Time.timeScale = 10.0f;if (Input.GetKeyDown(KeyCode.P))Time.timeScale =0.0f;}
6.预制体
预制体:Perfab,预先准备好的物体,可以重复使用,是Unity中很重要的资源。
预制体的创建方法:
- 手动创建:从Hierachy面板用鼠标拖拽游戏物体到Asserts资源文件夹中;
- 脚本动态创建:Instantiate(Prefabs,transform.position,transform.rotation);
- 可以置入多个场景中,也可以多次置入一个场景中。
- 在场景中添加一个Prefab,即实例化了一个预制体对象。
- 所有的Prefab实例都是一个Prefab的原型克隆,运行中生成的对象会有Clone的标记。
- 只要原型发生变化,所有的Prefabs都会发生变化。
创建游戏对象的三种方法:
- 通过GameObject构造函数创建游戏对象,生成一个空的游戏对象。
GameObject g=new GameObject(“g”); - 通过CreatePrimitive方法创建原型的游戏模型。GameObject.CreatePrimitive(Primitive.Cube);
- 通过Instantiate方法创建游戏对象。
克隆预制体;
克隆普通的游戏对象;
Instantiate(Prefabs,transform.position,transform.rotation);
public GameObject CubePrefab;private GameObject g2;GameObject g1;void Start(){g1= new GameObject("g1");GameObject.CreatePrimitive(PrimitiveType.Cube);Vector3 pos = new Vector3(-1f, 2f, 0f);//使用as将Instantiate的返回值转化为GameObject类型g2=Instantiate(CubePrefab, pos, Quaternion.identity) as GameObject;print(g2.name);}
运行前将准备好的预制体赋值给CubePrefab,如下:
结果如图:
游戏对象的销毁:
- 现在销毁一个对象,GameObject.Destroy(Object);
- 延迟销毁一个对象,GameObject.Destroy(Object obj,float time);
- 销毁游戏物体时将销毁该物体所有组件和子物体。
void Update(){if (Input.GetKeyDown(KeyCode.D)){GameObject.Destroy(g2);GameObject.Destroy(g1, 5f);}}
7.查找物体
若物体没激活,则通过名称和标签查不到,通过路径和和根据父物体可以查到。
方法 | 说明 |
---|---|
GameObject.Find() | 可通过名称全局查找或根据路径查找子对象 |
GameObject.Find(“Cube”).transform.GetChild(0) | 通过父物体查找子物体 |
FindWithTag/FindGameObjectWithTag/FindGameObjectsWithTag | 通过标签名查找 |
GameObject go1=GameObject.Find("s");print(go1.name);Transform tf1= transform.Find("g1/s");print(tf1);Transform tf2=GameObject.Find("g1").transform.GetChild(0);print(tf2);//设置s和g2的标签为Player;GameObject go2=GameObject.FindGameObjectWithTag("Player");print(go2);GameObject[] gArray = GameObject.FindGameObjectsWithTag("Player");print(gArray.Length);print(gArray[0].name);
8.启用和禁用
函数 | 功能 |
---|---|
SetActive | 参数true为启用,false为禁用 |
activeSelf | 父物体禁用,自身未禁用,则返回true |
activeInHierarchy | 父物体禁用,则返回false |
public GameObject Cube;void Update(){if (Input.GetKeyDown(KeyCode.D)){Cube.SetActive(false);print(Cube.activeSelf);print(Cube.activeInHierarchy);}if (Input.GetKeyDown(KeyCode.A)){Cube.SetActive(true);print(Cube.activeSelf);print(Cube.activeInHierarchy);}}
获取组件信息
void Start(){BoxCollider box= gameObject.GetComponent<BoxCollider>();box.size *= 3;//获取脚本组件s c=gameObject.GetComponent<s>();c.name = "txy";c.print();}
组价的启用和禁用
void Update(){//组件的添加和删除if(Input.GetKeyDown(KeyCode.A)){gameObject.AddComponent<Rigidbody>();}if (Input.GetKeyDown(KeyCode.D)){GameObject.Destroy(gameObject.GetComponent<Rigidbody>());}//组件的启用和禁用if (Input.GetKeyDown(KeyCode.E)){gameObject.GetComponent<BoxCollider>().enabled = true;}if (Input.GetKeyDown(KeyCode.F)){gameObject.GetComponent<BoxCollider>().enabled =false ;}}
移动物体
void Update(){//控制物体的移动//1.通过改变位置信息,添加一个增量,来持续改变位置信息transform.position += new Vector3(Time.deltaTime * 0.5f,0, 0);//2.通过transform.Translate来移动,默认朝自身坐标系方向运动,可以设置为朝世界坐标系transform.Translate(Vector3.right * Time.deltaTime * 0.5f,Space.World);//3.通过Vector3.Lerp方法,通过插值,运动为先快后慢Vector3 target = new Vector3(4f, 3f, 2f);transform.position=Vector3.Lerp(transform.position, target, Time.deltaTime);//4.通过Vector3.MoveTowards方法,匀速移动,z增量为Time.deltaTimetransform.position = Vector3.MoveTowards(transform.position, target, Time.deltaTime);//5.通过A,S,D,W键来控制物体的移动;虚拟轴的值正负来控制移动的方向float h = Input.GetAxis("Horizontal");float v = Input.GetAxis("Vertical");transform.Translate(Vector3.right * h * Time.deltaTime);transform.Translate(Vector3.forward * v * Time.deltaTime);}
物体的旋转
void Start(){//欧拉角与四元素介绍//获取物体的欧拉角print(transform.eulerAngles);//获取四元数print(transform.rotation);//四元素与欧拉角的相互转换print(transform.rotation.eulerAngles);//四元数-->欧拉角print(Quaternion.Euler(transform.eulerAngles));// 欧拉角-- > 四元数}// Update is called once per framevoid Update(){//1.使用transform.Rolate方法,y轴每秒旋转30度transform.Rotate(Vector3.up * Time.deltaTime * 30);//2.使用四元数的乘法来实现,在其基础上y轴旋转5度;Quaternion q1 = transform.rotation;Vector3 vd = new Vector3(0, 5, 0);Quaternion q2 = Quaternion.Euler(vd);if(Input.GetKeyDown(KeyCode.R)){transform.rotation=q1* q2;} }
Invoke相关方法
函数 | 功能 |
---|---|
Invoke(string funname,float time) | 调用函数。多少秒后执行函数funname,只会调用一次 |
InvokeRepeating(string ,float,float) | 重复调用函数。多少秒后执行某个函数,并且以后每个多少秒都会执行该函数一次 |
CancelInvoke | 取消这个脚本中的所有Invoke调用 |
CancelInvoke(string fun) | 取消某个函数的Invoke调用 |
IsInvokeing(string ) | 判断某个函数是否在等待调用 |
void Start(){//调用函数CreateBox,延迟两秒// Invoke("CreateBox", 2f);InvokeRepeating("CreateBox", 4f, 2f);}// Update is called once per framevoid Update(){bool r = IsInvoking("CreateBox");print(r);if(Input.GetKeyDown(KeyCode.D)){//CancelInvoke();CancelInvoke("CreateBox");}}void CreateBox(){print("生成物体");}
}
9.协成
协成:协成程序,即主程序在运行的同时开启另外一段出路逻辑。
协成方法与普通方法的区别:
- 调用普通方法,会等这个普通方法执行完,然后在继续向下执行;
- 调用协成方法,可以不用等这个方法执行完就继续向下执行;
协成方法的定义:
- 返回值类型是IEnumerator,方法体中使用yield return返回,可以返回空。
- 使用yield语句可以暂停协成的执行,yield return的返回值决定了什么时候恢复协成的执行。
例子 | 说明 |
---|---|
yield return null/数字/字符串 | 暂停协成,下一帧在继续执行,用来延迟一帧执行 |
yield return new WaitForSeconds(2f) | 暂停协成,2秒后再往下执行 |
yield return StartCoroutine(“Funname”) | 暂停协成,启动协成Funname,执行完后再继续往下执行 |
yeild new WaitForFixedUpdate() | 暂停协成,等下一次调用FixedUpdate方法是在继续执行下去 |
void Start(){//普通方法print("任务1");print("任务2");//print("任务3");//开启协成StartCoroutine("Task3");print("任务4");}//定义协成IEnumerator Task3(){yield return new WaitForSeconds(2f);print("任务3");}
结果
void Update(){//停止协成if(Input.GetKeyDown(KeyCode.Space)){StopCoroutine("Task3");}}
10.物理引擎
具有刚体组件的物体,满足物理规律,具有碰撞体的物体能进行碰撞检测。
- Mass表示物体的重量
- Drag:空气阻力
- Angular Drag:角阻力,受到扭曲时的空气阻力
- Use Gravity:使用重力
private Rigidbody r;// Start is called before the first frame updatevoid Start(){r = gameObject.GetComponent<Rigidbody>();}// Update is called once per framevoid Update(){//刚体移动float h = Input.GetAxis("Horizontal");float v = Input.GetAxis("Vertical");r.MovePosition(r.position + transform.right * h * Time.deltaTime * 2f);r.MovePosition(r.position + transform.forward * v * Time.deltaTime * 2f);}
碰撞事件检测方法
函数 | 功能 |
---|---|
OnCollisionEnter(Collision) | 当碰撞开始时,调用该方法一次 |
OnCollisionExit(Collision) | 当碰撞结束时,调用该方法一次 |
OnCollisionStay(Collision) | 当碰撞进行中是,持续调用该方法 |
private void OnCollisionEnter(Collision collision){print("Enter"+collision.gameObject.name);}private void OnCollisionExit(Collision collision){print("Enter" + collision.gameObject.name);}private void OnCollisionStay(Collision collision){print("Enter" + collision.gameObject.name);}
碰撞检测条件
- 两个物体接触并发生碰撞
- 运动物体必须带有碰撞体Collider和刚体Rigidbody
- 另一个物体必须至少带有碰撞体Collider
触发器事件
- 触发器:将碰撞组件属性面板上的“Is Trigger”勾选,当前物体的碰撞体就变成了了触发器。
- 触发器事件:当一个刚体控制的物体进入另一个物体的触发器范围内,就是触发事件。
- 用途:不与目标物体发生碰撞(接触),而是进入目标物体的触发范围,就执行特定操作。
触发器检测条件:
- 运动物体必须带有碰撞体Collider和刚体Rigidbody;
- 另一个物体至少带有碰撞体Collider;
- 其中一个物体勾选Is Trigger;
private void OnTriggerEnter(Collider other){if(other.name !="Plane"){print(other.gameObject.name);print(other.name);}}private void OnTriggerExit(Collider other){if (other.name != "Plane"){print(other.gameObject.name);print(other.name);}}private void OnTriggerStay(Collider other){if (other.name != "Plane"){print(other.gameObject.name);print(other.name);}}
物理射线
- 从一个点往一个方向发射,该射线与场景中的物体的碰撞体组件碰撞,射线即结束。
- 由于射线可以与物理组件Collider交互,所以也称之为“物理射线”;
物理射线检测方法:
- 通过摄像机创建射线
Camera.main:指的是tag设置为MainCamera的摄像机的组件Camera的引用;
ScreenPointToRay(Vector3):摄像机组件的下的方法,屏幕点转化为射线,返回一个Ray类型的射线。
Input.mousePosition:鼠标所在的位置,Vector3类型; - 检测射线与其他物体的碰撞
RaycastHit:一个结构体,存储射线的碰撞信息;
Physics.Raycast(Ray,out RaycastHit):检测射线,碰撞返回true,否则返回false;第一个参数为需要检测的射线,第二个参数存储碰撞信息。
private Ray ray;private RaycastHit hit;void Update(){if(Input.GetMouseButtonDown(0)){//获取摄像机,创建一条射线,方向为摄像机到鼠标点击的位置ray = Camera.main.ScreenPointToRay(Input.mousePosition);}//碰撞检测,通过结构体hit和返回关键字out返回碰撞信息if(Physics.Raycast(ray, out hit)){//把碰撞的物体销毁GameObject.Destroy(hit.collider.gameObject);}}
附:
学习至中国大学mooc-Unity2D游戏程序设计