-
Notifications
You must be signed in to change notification settings - Fork 22
Unity脚本
脚本是附加在游戏物体上用于定义游戏对象行为的指令代码
unity脚本在执行时是单线程的
Unity支持三种高级编程语言:C#/JavaScript
using UnityEngine;
using 其他命名空间;
public class 类名 : MonoBehaviour
{
void 方法名()
{
Debug.Log("调试显示信息");
}
}
文件名和类名必须一致
写好的脚本必须附加在物体上才执行
,物体会创建一个这个脚本的类对象
附加到游戏物体的脚本类必须从MonoBehaviour类继承
C:\Program Files\Unity\Editor\Data\Resources\ScriptTemplates
可以进行编辑
比如 81-C# Script-NewBehaviourScript.cs.txt
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class #SCRIPTNAME# : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
#NOTRIM#
}
// Update is called once per frame
void Update()
{
#NOTRIM#
}
}
1.脚本里面的public变量会显示在编辑器里面
tips:在类文件中设置Test=100;在Unity编辑器中设置Test=200,最终得到Test=200
因为Test是对象的字段,在Unity编辑器中操作的是对象
2.脚本中的private变量,可以通过[SerializeField]可以被Unity编辑器访问
即该变量希望被Unity编辑器访问,不希望被其他类访问
3.希望脚本中的public变量不被编辑器访问
使用[HideInInspector]特性
4.希望给变量加范围
[Range(0,120)]
public int Test4;
1.编辑器不区分首字母大小写,在编辑器中不显示属性
不建议使用私有字段和属性结合的方式写,直接写字段
2.不能在子线程中访问主线程成员->构造函数中不能访问Unity提供的功能->在脚本中通常不写构造函数
而且Unity会调用两次构造函数,不符合预期
当挂载多个脚本,且脚本之间有依赖关系,使用[RequireComponent]
public RequireComponent(Type requiredComponent);
这样在Inspector里面只用挂载最后一个依赖脚本,其他的脚本自动挂载
链接
Unity脚本从唤醒到销毁的过程
消息/必然事件:当满足某条件Unity引擎自动调用的函数
生命周期=消息/必然事件
视频链接
完整的生命周期,看官网
生命周期图
下面是比较重要的生命周期
初始化,用Awake和Start代替构造函数
1.Awake 唤醒
当物体载入时立即调用1次,常用于在游戏开始前进行初始化
执行时机:游戏物体创建->立即执行Awake(早于Start)
禁用物体时,不执行Awake;不禁用物体,禁用脚本时,会执行Awake
可以判断当满足某条件时启动当前脚本
//关系是否启动该脚本,是否执行Start和OnEnable
this.enabled = true;
2.Start
物体载入且脚本对象启用时被调用1次,常用于数据或者游戏逻辑初始化
执行时机:游戏物体创建->脚本启动->执行Start
禁用物体时,不执行Start;不禁用物体,禁用脚本时,不执行Start
tips:
a.先执行Awake再执行Start
在所有物体的Awake执行完成后,再执行所有物体的Start
->初始化游戏数据,可以通过Awake和Start方法来区分先后顺序
b.仅初始化的时候执行一次,脚本从禁用到启动不再执行Awake和Start
3.OnEnable
执行时机:每当脚本对象启用时执行
1.FixedUpdate 固定更新
执行时机:脚本启用后,每隔固定时间被调用
适用性:适用于对游戏对象做物理操作,比如移动等
不会受到渲染影响
(渲染时间不固定:每帧渲染工作量不同、机器性能不同)
设置更新频率:Edit->Project Setting->Time->Fixed Timespan
默认值为0.02s,不建议修改,改大了失真,改小了增大消耗
2.OnCollisionXXX 碰撞
当满足碰撞条件时调用
3.OnTriggerXXX 触发
当满足触发条件时调用
1.Update
脚本启用后,每次渲染场景时调用,频率和设备性能与渲染量有关
执行时机:渲染帧执行,执行间隔不固定
适用性:处理游戏逻辑(有些游戏也会把FixedUpdate的工作放到Update中执行)
tips:注意与FixedUpdate的区别
2.LateUpdate 延迟更新
在Update函数被调用后执行,适用于跟随逻辑
LateUpdate与Update在同一帧执行,在Update后面执行
eg.人物移动(Update),摄像机跟随(LateUpdate)
注意物体必须有Collider(碰撞器)
鼠标移入
当前Collider
时调用
鼠标经过
当前Collider
时调用
鼠标离开
当前Collider
时调用
鼠标按下
当前Collider
时调用
鼠标在当前Collider
被抬起
时调用
链接
包装了输入功能的类,可以读取输入管理器中设置的按键,以及访问移动设备的多点触控或加速感应数据
建议在Update()中监控用户的输入(建议用事件机制替换在Update()中判断的方式)
1.获得键盘输入
//button:0-左键,1-右键,2-中键
//指定的鼠标按钮被按下时返回true(持续)
public static bool GetMouseButton(int button);
//用户按下指定鼠标按钮的第一帧返回true
public static bool GetMouseButtonDown(int button);
//用户释放指定鼠标按钮的第一帧返回true
public static bool GetMouseButtonUp(int button);
//eg.
bool result= Input.GetMouseButton(0);
2.获得键盘输入
//类似GetMouseButton/GetMouseButtonDown/GetMouseButtonUp
public static bool GetKey(KeyCode key);
public static bool GetKeyDown(KeyCode key);
public static bool GetKeyUp(KeyCode key);
public static bool GetKey(string name);
public static bool GetKeyDown(string name);
public static bool GetKeyUp(string name);
注意键盘左右两边的重复按键在KeyCode中有区分
KeyCode.LeftControl
KeyCode.RightControl
两个按键同时检测,取&&
前提是该物体必须有Mesh Render
1.OnBecameVisible 当可见
当Mesh Render在任何相机上可见时调用
2.OnBecameInvisible 当不可见
当Mesh Render在任何相机上不可见时调用
1.OnDisable 当不可用
对象变为不可用或者附属游戏对象非激活状态时此函数被调用
每次物体被禁用都会调用OnDisable
2.OnDestroy 当销毁
当脚本销毁或附属的游戏对象被销毁时被调用
3.OnApplicationQuit 当程序结束
应用程序退出时被调用
/// <summary>
/// 生命周期/消息/必然事件
/// </summary>
public class Lifecycle : MonoBehaviour
{
/******************************************初始化阶段****************************************************/
//执行时机:游戏物体创建->立即执行Awake(早于Start)
//作用:初始化,代替构造函数
//仅初始化的时候执行一次
private void Awake()
{
//可以判断当满足某条件时启动当前脚本
//关系是否启动该脚本,是否执行Start和OnEnable
//this.enabled = true;
//Debug.Log($"Awake:{Time.time} {this.name}");
}
//执行时机:游戏物体创建->脚本启动->执行Start
//作用:初始化,代替构造函数
//仅初始化的时候执行一次
private void Start()
{
Debug.Log($"Start:{Time.time} {this.name}");
}
//执行时机:每当脚本对象启用时执行
private void OnEnable()
{
//Debug.Log($"OnEnable:{Time.time} {this.name}");
}
/******************************************************物理阶段*************************************************/
//执行时机:每隔固定时间执行一次(时间可修改)
//适用性:适合对物体做物理操作(移动、旋转等),不会受到渲染影响(渲染时间不固定:每帧渲染工作量不同、机器性能不同)
private void FixedUpdate()
{
//Debug.Log($"FixedUpdate:{Time.time} {this.name}");
}
//碰撞事件
private void OnCollisionEnter(Collision collision)
{
}
//触发事件
private void OnTriggerEnter(Collider other)
{
}
/******************************************************游戏逻辑阶段*************************************************/
//执行时机:渲染帧执行,执行间隔不固定
//适用性:处理游戏逻辑
private void Update()
{
}
//在Update函数被调用后执行,适用于跟随逻辑
private void LateUpdate()
{
}
/******************************************************输入阶段*************************************************/
//鼠标移入
private void OnMouseEnter()
{
}
//鼠标经过
private void OnMouseOver()
{
}
//鼠标离开
private void OnMouseExit()
{
}
//鼠标按下
private void OnMouseDown()
{
Debug.Log("OnMouseDown");
}
//鼠标抬起
private void OnMouseUp()
{
}
/******************************************************场景渲染阶段*************************************************/
//当Mesh Render在任何相机上可见时调用
private void OnBecameVisible()
{
}
//当Mesh Render在任何相机上不可见时调用
private void OnBecameInvisible()
{
}
/******************************************************结束阶段*************************************************/
//对象变为不可用或者附属游戏对象非激活状态时此函数被调用
//每次物体被禁用都会调用OnDisable
private void OnDisable()
{
}
//当脚本销毁或附属的游戏对象被销毁时被调用
private void OnDestroy()
{
}
//应用程序退出时被调用
private void OnApplicationQuit()
{
}
}
将程序投入实际运行中,通过开发工具进行测试,修正逻辑错误的过程
1.控制台调试
Debug.Log("");
print("");
2.定义共有变量(前端显示的变量),程序运行后在监测面板(Inspector)查看数据
适用于数据变化快的,想查看规律的变量
tips:最后发布游戏前,记住删除Debug.Log/Debug变量
3.创建按钮在界面上点击调用
private void OnGUI()
{
if (GUILayout.Button("按钮"))
{
//调用测试方法
}
}
链接
准备工作
1.安装VS,Unity
2.在Unity项目面板中导入VS Tools
调试步骤
1.打断点
2.VS中启动调试(Attach to Unity)
3.在Unity中Play场景