1.脚本基本规则
1.设置编程用工具
2.基本规则
1.创建规则
- 不在VS中创建脚本了
- 可以放在Assets文件夹下的任何位置(建议同一文件夹管理)
- 类名和文件名必须一致,不然不能挂载(因为反射机制创建对象,会通过文件名去找Type)
- 建议不要使用中文名命名
- 没有特殊需求不用管命名空间
- 创建的脚本默认继承MonoBehavior
2.MonoBehavior基类
物体脚本的类都继承MonoBahaviour基类(只有继承类MonoBahaviour类才能挂载到GameObject上)
- 创建的脚本默认都继承MonoBehaviour继承了它才能够挂载在GameObject上
- 继承了MonoBehavior的脚本不能new只能挂!!!!!!!!
- 继承了MonnBehavior的脚本不要去写构造函数,因为我们不会去new它。写构造函数没有任何意义
- 继承了MonoBehavior的脚本可以在一个对象上挂多个(如果没有加DisallowMultipleComponent特性)
- 继承MonoBehavior的类也可以再次被继承,遵循面向对象继承多态的规则
3.不继承MonoBehavior的类
- 不继承Mono的类不能挂载在GameObject上
- 不继承Mono的类想怎么写怎么写如果要使用需要自己new
- 不继承Mono的类一般是单例模式的类(用于管理模块)或者数据结构类(用于存储数据)
- 不继承Mono的类不用保留默认出现的几个函数
4.执行的先后顺序
选中一个脚本点击Execution Order键:
会显示如下窗口:
点击下图的+按钮可以设置脚本执行顺序:
可以添加脚本(NewBehaviourScript是新添加的继承MonoBehaviour类的脚本)
5.默认脚本内容Editor\Data\Resources\ScriptTemplates
2.生命周期函数
1.了解帧的概念
游戏的本质就是一个死循环,每一次循环处理游戏逻辑就会更新—次画面,之所以能看到画面在动,是因为切换画面的速度到达一定时,人眼就认为画面是流畅的,—帧就是执行一次循环
游戏卡顿的原因:跑1帧游戏逻辑中的计算量过大,或者CPU不给力,不能在一帧的时间内处理完所有游戏逻辑
Unity 底层已经帮助我们做好了死循环
我们需要学习Unity的生命周期函数
利用它做好的规则来执行我们的游戏逻辑就行了
2.生命周期函数的概念
所有继承 MonoBehaviour 的脚本 最终都会挂载到GameObject游戏对象上
生命周期函数 就是该脚本对象依附的GameObject对象从出生到消亡整个生命周期中会通过反射自动调用的一些特殊函数
Unity帮助我们记录了一个GameObject对象依附了哪些脚本
会自动的得到这些对象,通过反射去执行一些固定名字的函数
3.生命周期函数
注意:
生命周期函数的访问修饰符一般为 private和 protected
因为不需要在外部自己调用生命周期函数 都是 Unity 自己帮助我们调用的
当对象(自己这个类对象) 被创建时 才会调用该生命周期函数
private void Awake()
{
//在Unity中打印信息的两种方式
//1.没有继承MonoBehaviour类的时候
//Debug.Log("123");
//Debug.LogError("出错了");
//Debug.LogWarning("警告");
//2.继承了MonoBehaviour 有一个线程的方法 可以使用
print("Awake");
}
//对于我们来说 想要当一个对象被激活时 进行一些逻辑处理 就可以写在这个函数
private void OnEnable()
{
print("OnEable");
}
//主要作用还是用于初始化信息的 但是它相对于Awake来说 要晚一点
//因为它是在对象 进行第一次帧更新之前才会执行的
private void Start()
{
print("Strart");
}
//它主要是用于 进行物理更新
//它是每一帧的执行的 但是 这里的帧 和游戏帧 有点不同
//它的时间间隔 是可以在 protect setting中的 Time里去设置的
private void FixedUpdate()
{
print("FixedUpdate");
}
//主要用于处理游戏核心逻辑更新的函数
private void Update()
{
print("Update");
}
//一般这个更新是用来处理 摄像机位置更新相关内容的
//Update 和 LateUpdate 之间 Unity 进行了一些处理 处理我们动画相关的更新
private void LateUpdate()
{
print("LateUpdate");
}
//如果我们希望在一个对象失活时做一些处理 就可以在该函数中写逻辑
private void OnDisable()
{
print("OnDisable");
}
private void OnDestroy()
{
print("OnDestroy");
}
4.生命周期函数 支持继承多态
(这些生命周期函数 如果你不打算在其中写逻辑 那就不要写出这些生命周期函数 )
3.inspector窗口可编辑的变量
1.Inspector显示的可编辑内容就是脚本的成员变量
2.私有和保护无法显示编辑
private int i1;
protected string str1;
3.让私有的和保护的也可以被显示
加上强制序列化字段特性
[SerializeField]
所谓序列化就是把一个对象保存到一个文件或数据库字段中去
[SerializeField]
private int privateInt;
[SerializeField]
protected string protectedStr;
4.公共的可以显示编辑
[HideInInspector]
public int publicInt = 10;
public bool publicBool = false;
5.公共的也不让其显示编辑
在变量前加上特性 [HideInInspector]
[HideInInspector]
public int publicInt2 = 50;
6.大部分类型都能显示编辑
public enum E_TestEnum
{
Normal,
Player,
Monster
}
[System.Serializable]
public struct MyStruct
{
public int age;
public bool sex;
}
[System.Serializable]
public class MyClass
{
public int age;
public bool sex;
}
public int[] array;
public List<int> list;
public E_TestEnum type;
public GameObject gameObj;
//字典不能被Inspector窗口显示
public Dictionary<int, string> dic;
//自定义类型变量
public MyStruct myStruct;
public MyClass myClass;
7.让自定义类型可以被访问
加上序列化特性 [System.Serializable]
字典怎样都不行
8.一些辅助特性
1.分组说明特性 Header
为成员分组
Header 特性 [Header("分组说明")]
[Header("基础属性")]
public int age;
public bool sex;
[Header("战斗属性")]
public int atk;
public int def;
2.悬停注释 Tooltip
为变量添加说明 [Tooltip("说明内容")]
[Tooltip("闪避")]
public int miss;
3.间隔特性 Spcae()
让两个字段间出现间隔 [Space()]
[Space()]
public int crit;
4.修饰数值的滑条范围 Range
[Range(最大值,最小值)]
[Range(0,10)]
public float luck;
5.多行显示字符串 默认不写参数显示3行
写参数就是对应行[Multiline(4)]
[Multiline()]
public string tips;
6.滚动条显示字符串
默认不写参数就是超过三行显示滚动条 [TextArea(3,4)]
最少显示3行,最多4行,超过四行就显示滚动条
[TextArea(3, 4)]
public string MyLife;
7.为变量添加快捷方法 ContextMenuItem
参数1 显示按钮名
参数2 方法名 不能有参数
[ContestMenuItem("显示按钮名","方法名")]
[ContextMenuItem("重置钱", "Test")]
public int money;
private void Test()
{
money = 0;
}
8.为方法添加特性能够在Inspector中执行
[ContextMenu("测试函数")]
[ContextMenu("哈哈哈")]
private void TestFun()
{
print("测试方法");
}
9.注意
1.Inspector窗口中的变量关联的就是对象的成员变量,运行时改变他们就是在改成员变量
2.拖曳到GameObject对象后 再改变脚本中变量默认值 界面上不会改变
3.运行中修改的信息不会保存
4.MonoBehaviour中的重要内容
1.重要成员
1.获取依附的GameObject
print(this.gameObject.name);
2.获取依附的GameObject的位置信息
得到对象位置信息文章来源:https://www.toymoban.com/news/detail-406263.html
print(this.transform.position); //位置
print(this.transform.eulerAngles);//角度
print(this.transform.lossyScale); //缩放大小
//这种写法和上面都是一样的效果 都是得到依附的对象的位置信息
//this.gameObject.transform
3.获取脚本是否激活
this.enabled = true; //激活
this.enabled = false;//失活
//获取别的脚本对象 衣服的gameObject和transform位置信息
print(otherLesson3.gameObject.name);
print(otherLesson3.transform.position);
2.重要方法
得到依附对象上挂载的其他脚本 文章来源地址https://www.toymoban.com/news/detail-406263.html
1.得到自己挂载的单个脚本
//根据脚本名获取
lesson3_Test t=this.GetComponent("lesson3_Test") as lesson3_Test;
print(t);
//根据Type获取
t = this.GetComponent(typeof(lesson3_Test)) as lesson3_Test;
print(t);
//根据泛型获取 建议使用泛型获取 因为不用二次转换
t = this.GetComponent<lesson3_Test>();
if (t != null)
{
print(t);
}
//只要你能够得到场景中别的对象或者对象依附的脚本
//那你就可以获取到它的所有信息
2.得到自己挂载的多个脚本
lesson3[] array = this.GetComponents<lesson3>();
print(array.Length);
List<lesson3> list = new List<lesson3>();
this.GetComponents<lesson3>(list);
print(list.Count);
3.得到子对象挂载的脚本(它默认也会找自己身上是否挂载该脚本)
//函数是有一个参数的 默认不传 是false
//意思就是 如果子对象失活 是不会去找这个对象上是否有某个脚本
//如果传 true 即使失活 也会找
t = this.GetComponentInChildren<lesson3_Test>();
print(t);
//得子对象 挂载脚本 多个
lesson3_Test[] lts = this.GetComponentsInChildren<lesson3_Test>(true);
print(lts.Length);
List<lesson3_Test> list2 = new List<lesson3_Test>();
this.GetComponentsInChildren<lesson3_Test>(true, list2);
4.得到父对象挂载的脚本(它默认也会找自己身上是否挂载了该脚本)
t = this.GetComponentInParent<lesson3_Test>();
print(t);
lts = this.GetComponentsInParent<lesson3_Test>();
print(lts.Length);
//它也有list的 和上面相同的套路
5.尝试获取脚本
lesson3_Test l3t;
//提供了一个更加安全的 获取单个脚本的方法 如果得到了 会返回true
//然后再来进行逻辑处理即可
if (this.TryGetComponent<lesson3_Test>(out l3t))
{
//逻辑处理
}
到了这里,关于Unity入门03——Unity脚本的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!