当前位置:   article > 正文

Unity脚本设计基础(持续补充中...)_unity primitivetype

unity primitivetype

一、常用组件和函数

1:MonoBehaviour的父类

当我们从Unity中打开C#脚本时,可以看到这一行

public class Demo2 : MonoBehaviour

意味着我们在Unity中所有的对象都是继承自MonoBehaviour的

选中MonoBehaviour后点击F12,可以看到

public class MonoBehaviour : Behaviour

MonoBehaviour是继承自Behaviour的,继续点击F12

public class Behaviour : Component

Behaviour是继承自Component的,对Component进行查找,可以看到

public class Component : Object

它其实是继承自Object类的,而继续追踪下去我们可以看到

  1. public class Object
  2. {
  3. public Object();
  4. //
  5. // 摘要:
  6. // Should the object be hidden, saved with the Scene or modifiable by the user?
  7. public HideFlags hideFlags { get; set; }
  8. //
  9. // 摘要:
  10. // The name of the object.
  11. public string name { get; set; }
  12. //
  13. // 摘要:
  14. // Removes a GameObject, component or asset.
  15. //
  16. // 参数:
  17. // obj:
  18. // The object to destroy.
  19. //
  20. // t:
  21. // The optional amount of time to delay before destroying the object.
  22. [NativeMethodAttribute(Name = "Scripting::DestroyObjectFromScripting", IsFreeFunction = true, ThrowsException = true)]
  23. public static void Destroy(Object obj, [DefaultValue("0.0F")] float t);

最起始我们其实是创建了Object类的,然后是一层一层的继承关系

2:GameObject对象

我们可以在Component中找到GameObject,而GameObject其实是来自与Object

public sealed class GameObject : Object

通常情况下,GameObject表示场景中的基本单元或者实体,比如声音,碰撞器,管理类都是,可见的状态包括网格,动画网格,精灵对象等,而每个GameObject至少包含一个组件且不可移除,就是Transform组件,transform和gameObject之间

public class Transform : Component, IEnumerable

可以相互引用嵌套。

因此GameObject由组件构成,而在较高层面上,场景则由单一场景内的GameObject的集合构成

涉及GameObject的方法如下、

  1. public GameObject();
  2. public GameObject(string name);
  3. public GameObject(string name, params Type[] components);
  4. public static GameObject CreatePrimitive(PrimitiveType type);
  5. public static GameObject Find(string name);
  6. public static GameObject[] FindGameObjectsWithTag(string tag);
  7. public static GameObject FindGameObjectWithTag(string tag);
  8. public static GameObject FindWithTag(string tag);

gameObject(当前组件所在得游戏物体)中的常用属性和方法

属性:

Name:游戏物体名称,和层级面板中等同

Tag:游戏物体得标签

activeInHierarchy:显示状态

Transform:这个游戏物体的变换组件

方法:

1):GetComponent<T>():获取游戏物体身上的组件,T代表要查找的类型,类型的方法有很多

2):SetActive(bool):修改显示状态

3):Static GameObject Find(string path):一个静态方法,查找游戏物体

部分代码段

  1. public class L2_6Demo : MonoBehaviour
  2. {
  3.     //transform和gameObject之间可以相互引用嵌套
  4.     private GameObject gO;   //改为private,外部就无法看到了
  5.     public Transform tS;
  6.     void Start()
  7.     {
  8.         获取当前组件所在得游戏物体
  9.         print(gameObject);  
  10.         print(gO);  
  11.         print(gameObject.transform.position);
  12.         print(gO.transform.position);  //因为gO已经定义为GameObject类型,所以也可以直接引用transform
  13.         print(tS);
  14.         print(tS.position);
  15.         print(tS.gameObject);
  16.        
  17.         Transform tempTransform = gameObject.GetComponent<Transform>();  
  18.         GameObject gO = gameObject.GetComponent<GameObject>();  
  19.         // <>里面要填写你要获取的物体类型,此处填什么就返回什么类型
  20.         //比如上面一个是Transform类型的,后面写了,前面返回类型就是Transform
  21.        
  22. //下面写了Gameobject类型的,前面回来也就必须是Gameobject
  23.         print(tempTransform.position);
  24.         print(gO.name);  //后面报错了,因为Gameobject严格的来说不算组件
  25.         //所以正常情况下,我们都是用Transform来进行泛型返回值的规定
  26.        
  27. BoxCollider boxCollider = gameObject.GetComponent<BoxCollider>();
  28.         print(boxCollider.isTrigger);
  29.         gameObject.SetActive(false);   //设置显示,false是隐藏我们的物体
  30.     }

3:Transform组件

对Transform进行父类查询可以看到

public class Transform : Component, IEnumerable

Transform中的方法非常多,我们将每一条都列出来

  1. public Vector3 localPosition { get; set; }
  2. public Vector3 eulerAngles { get; set; }
  3. public Vector3 localEulerAngles { get; set; }
  4. public Vector3 right { get; set; }
  5. public Vector3 up { get; set; }
  6. public Vector3 forward { get; set; }
  7. public Quaternion rotation { get; set; }
  8. public Vector3 position { get; set; }
  9. public Quaternion localRotation { get; set; }
  10. public Transform parent { get; set; }
  11. public Matrix4x4 worldToLocalMatrix { get; }
  12. public Matrix4x4 localToWorldMatrix { get; }
  13. public Transform root { get; }
  14. public int childCount { get; }
  15. public Vector3 lossyScale { get; }
  16. public bool hasChanged { get; set; }
  17. public Vector3 localScale { get; set; }
  18. public int hierarchyCapacity { get; set; }
  19. public int hierarchyCount { get; }
  20. public void DetachChildren();
  21. public Transform Find(string n);
  22. public Transform FindChild(string n);
  23. public Transform GetChild(int index);
  24. public int GetChildCount();
  25. public IEnumerator GetEnumerator();
  26. public int GetSiblingIndex();
  27. public Vector3 InverseTransformDirection(Vector3 direction);
  28. public Vector3 InverseTransformDirection(float x, float y, float z);
  29. public Vector3 InverseTransformPoint(float x, float y, float z);
  30. public Vector3 InverseTransformPoint(Vector3 position);
  31. public Vector3 InverseTransformVector(Vector3 vector);
  32. public Vector3 InverseTransformVector(float x, float y, float z);
  33. public bool IsChildOf([NotNullAttribute("ArgumentNullException")] Transform parent);
  34. public void LookAt(Transform target, [DefaultValue("Vector3.up")] Vector3 worldUp);
  35. public void LookAt(Vector3 worldPosition, [DefaultValue("Vector3.up")] Vector3 worldUp);
  36. public void LookAt(Vector3 worldPosition);
  37. public void LookAt(Transform target);
  38. public void Rotate(float xAngle, float yAngle, float zAngle);
  39. public void Rotate(Vector3 eulers, [DefaultValue("Space.Self")] Space relativeTo);
  40. public void Rotate(Vector3 eulers);
  41. public void Rotate(float xAngle, float yAngle, float zAngle, [DefaultValue("Space.Self")] Space relativeTo);
  42. public void Rotate(Vector3 axis, float angle, [DefaultValue("Space.Self")] Space relativeTo);
  43. public void Rotate(Vector3 axis, float angle);
  44. public void RotateAround(Vector3 point, Vector3 axis, float angle);
  45. public void RotateAround(Vector3 axis, float angle);
  46. public void RotateAroundLocal(Vector3 axis, float angle);
  47. public void SetAsFirstSibling();
  48. public void SetAsLastSibling();
  49. public void SetParent(Transform p);
  50. public void SetParent(Transform parent, bool worldPositionStays);
  51. public void SetPositionAndRotation(Vector3 position, Quaternion rotation);
  52. public void SetSiblingIndex(int index);
  53. public Vector3 TransformDirection(float x, float y, float z);
  54. public Vector3 TransformDirection(Vector3 direction);
  55. public Vector3 TransformPoint(float x, float y, float z);
  56. public Vector3 TransformPoint(Vector3 position);
  57. public Vector3 TransformVector(float x, float y, float z);
  58. public Vector3 TransformVector(Vector3 vector);
  59. public void Translate(float x, float y, float z);
  60. public void Translate(float x, float y, float z, [DefaultValue("Space.Self")] Space relativeTo);
  61. public void Translate(Vector3 translation);
  62. public void Translate(Vector3 translation, [DefaultValue("Space.Self")] Space relativeTo);
  63. public void Translate(float x, float y, float z, Transform relativeTo);
  64. public void Translate(Vector3 translation, Transform relativeTo);

常用的属性如下:

childCount:子物体的数量

Parent:父物体的Transform组件

Root:最高级别父物体

  1. print(transform.childCount);  
  2.         print(transform.parent);
  3.         print(transform.root);
  4.         print(transform.eulerAngles);            //这里挂载到update上,实时旋转信息会更新
  5.        
  6.         print("当前坐标"+transform.position);    //print和Debug.Log是等价的,实时获取位置信息
  7.         print("当前旋转"+transform.rotation);    //这里改变旋转角度并不会实时显示
  8.         print("当前缩放"+transform.localScale);
  9.         transform.position = new Vector3(num,0,0);       //vector3中已经定义过了X,Y,Z,因此只需要在此处输入坐标即可
  10.         num+=0.01f;

常用的方法如下:

Find(string):查找子物体

Translate(Vetor3):朝着一个坐标移动

Rotate(Vetor3):旋转一个角度

LookAt(Transform):看向目标

  1. print(transform.Find("C")); //查找子物体
  2. transform.Translate(new Vector3(0.01f , 0, 0));   //游戏物体会依据给定方向进行位移,输入-0,01f则是向反方向位移
  3. transform.Rotate(new Vector3(3,0,0));     //vector3中的类型可以填int和float
  4. transform.LookAt(transform.parent); //原本朝向前方的立方体,会立即看向球的方向

4:GetComponent类函数

如果用户需要直接访问某一对象上的特定单一组件,且已知数据类型,则可以通过使用GetComponent函数进行引用,一旦引用,则可像常规对象一样访问该组件。该函数可以访问与GameObject绑定的组件

  1. public class L3_2Demo : MonoBehaviour
  2. {
  3. private SpriteRenderer spriteRenderer;
  4. void Start()
  5. {
  6. spriteRenderer=gameObject.GetComponent<SpriteRenderer>();
  7. spriteRenderer.sprite =null; //将sprite组件清空
  8. spriteRenderer.color= Color.black;//通过C#来改变颜色组件
  9. }

首先指定SpiteRenderer类型为Private,名称为spiteRenderer

其次在Start函数中进行派生类型转换。

这样的规定下,我们可以直接使用spiriteRenderer来访问和设置GameObject的一系列组件

我们可以从Component获取这些组件,这是和从Unity中添加列表对应的,当然了,Unity中的组件远不止这些。

  1. public Component rigidbody2D { get; }
  2. public Component camera { get; }
  3. public Component light { get; }
  4. public Component animation { get; }
  5. public Component constantForce { get; }
  6. public Component renderer { get; }
  7. public Component audio { get; }
  8. public Component networkView { get; }
  9. public Component collider { get; }
  10. public Component collider2D { get; }
  11. public Component rigidbody { get; }
  12. public Component hingeJoint { get; }

Component族函数

  1. public Component AddComponent(string className);
  2. public Component AddComponent(Type componentType);
  3. public T AddComponent<T>() where T : Component;
  4. public Component GetComponent(string type);
  5. public T GetComponent<T>();
  6. public Component GetComponent(Type type);
  7. public T GetComponentInChildren<T>();
  8. public T GetComponentInChildren<T>([Internal.DefaultValue("false")] bool includeInactive);
  9. public Component GetComponentInChildren(Type type);
  10. public Component GetComponentInParent(Type type, bool includeInactive);
  11. public Component GetComponentInParent(Type type);
  12. public T GetComponentInParent<T>();
  13. public T GetComponentInParent<T>([Internal.DefaultValue("false")] bool includeInactive);
  14. public void GetComponents<T>(List<T> results);
  15. public Component[] GetComponents(Type type);
  16. public T[] GetComponents<T>();
  17. public void GetComponents(Type type, List<Component> results);
  18. public void GetComponentsInChildren<T>(List<T> results);
  19. public T[] GetComponentsInChildren<T>();
  20. public void GetComponentsInChildren<T>(bool includeInactive, List<T> results);
  21. public T[] GetComponentsInChildren<T>(bool includeInactive);
  22. public Component[] GetComponentsInChildren(Type type, [Internal.DefaultValue("false")] bool includeInactive);
  23. public Component[] GetComponentsInChildren(Type type);
  24. public T[] GetComponentsInParent<T>();
  25. public void GetComponentsInParent<T>(bool includeInactive, List<T> results);
  26. public T[] GetComponentsInParent<T>(bool includeInactive);
  27. public Component[] GetComponentsInParent(Type type, [Internal.DefaultValue("false")] bool includeInactive);
  28. public Component[] GetComponentsInParent(Type type);
  29. public bool TryGetComponent(Type type, out Component component);
  30. public bool TryGetComponent<T>(out T component);

所有的方法都可以在具体的操作中使用,但是制作游戏内容时,不会用到太多的方法,只需要掌握常用的一些方法,其他的需要时再学习

5:生命周期函数

常用的生命周期函数如下

Awake():唤醒事件,一开始就执行,只执行一次

OnEnable():启用事件,每次启用都执行一次,当脚本组件被启用的时候执行一次。

Start():开始事件,执行一次。

FixedUpdate():固定更新事件,执行N次,0.02s执行一次。所有物理相关的更新都在这个事件上处理。

Update():更新事件,执行N次,每帧执行一次。

LateUpdate():执行后更新事件,执行N次,在update()和fixedupdate()事件执行完毕后再执行,可以确保当前帧的各个对象,update和fixedUpdate已被调用完成,因此它常常被用于更新相机运动,特别是第三人称相机,以使相机可于当前帧的最新位置尾随对象

OnDisable():禁用事件,每次禁用都执行一次。在OnDestroy()事件也会执行。

OnDestroy():销毁事件,执行一次,当组件被销毁时执行。

代码段

  1. private void Awake()
  2.     {
  3.         print("Awake");//只执行一次
  4.     }
  5.     private  void OnEnable()
  6.     {
  7.         print("Enable");   //每次重新激活cube的时候都会重新使用函数
  8.     }
  9.     private void OnDisable()
  10.     {
  11.         print("OnDisable");  //每次禁用cube的时候都会执行一次
  12.     }
  13.     void Start()
  14.     {
  15.         print("Start");     //只执行一次
  16.     }
  17.     void Update()
  18.     {
  19.         print("Update"); //每帧执行一次
  20.         //渲染上一帧的事件
  21.     }
  22.     private void LateUpdate()
  23. {
  24.         print("LateUpdate");
  25.     }
  26.     private void FixedUpdate()
  27.     {
  28.         print("FixedUpdate");
  29.     }
  30.     private void OnDestroy()
  31.     {
  32.         print("Ondestroy");    //当cube被销毁的时候会触发,同时ondisable也会执行
  33.     }

Invoke函数的调用和执行

Invoke(string methodName , float time );输入一个方法名称,过几秒执行一次

invokeRepeating(string methodName , float time ,float repeatRate):重复调用

Calcel Invoke(string methodName):取消调用,使用无参重载就是取消全部

代码段

  1. void Start()
  2.     {
  3.         Invoke("Demo",3);        //延迟3S后启动Demo函数
  4.        
  5.         InvokeRepeating("Demo",2,1);  //延迟2S后执行,每次间隔一秒执行一次
  6.        
  7.     }
  8.     private void CancelDemo ()
  9.     {
  10.         CancelInvoke("Demo");   //单独书写一个方法,再和invoke结合
  11.     }
  12.    
  13. public void Demo()
  14.     {
  15.         print("Demo");
  16.     }

6:协程函数

为什么需要协程?
主程序已经在执行某个任务,希望同时运行其他逻辑,而不是多线程的同时

协程函数的定义

  1. Public IEnumerator Demo() //协程特定返回值
  2. {
  3. Debug.Log(“做一些事情”);
  4. Yield return new WaitForSeconds(1.0f); //等待一秒钟
  5. Debug.Log(“做一些事情”); //协程不会因为前面返回而不执行后面的代码
  6. }

协程函数的使用

Coroutine StartCoroutine(Demo(“这是参数”))

执行一个协程,参数直接调用协程方法即可,可以用一个变量接受返回值用于后续停止该协程

我们在生命周期函数中调用协程,但是协程的运行顺序和主程序无关,可以理解为开了一个分支专门运行这个协程,如果我们打开了多个协程,这些协程之间也无关。

 协程函数的停止

协程如果运行到最后一行,意味着停止,但是如果我们想主动停止

StopAllCoroutines():结束全部协程

StopCoroutine:结束某个协程

        StopCoroutine(IEnumerator routine):和协程一样使用,但是如果协程有参数就不能使用

        StopCoroutine(Coroutine routine);参数填写协程变量

        StopCoroutine(string methodName):参数填写协程方法的名

代码段

  1. void Start()
  2.     {
  3.  
  4.         //Coroutine cor =StartCoroutine(Demo(10));  //通过构建此类cor,来停止
  5.         //StopCoroutine(cor);
  6.        
  7.         //StartCoroutine(Demo(10));  //第二种写法,好一点,可以传输参数
  8.         StartCoroutine("Demo2");
  9.         StartCoroutine("Demo3");
  10.         StartCoroutine("Demo4");
  11.     }
  12.  
  13.     //常规函数
  14.     public int GetNum()  //用来接收Demo返回值的
  15.     {
  16.         return 0;
  17.     }
  18.    
  19. //协程函数
  20.     public IEnumerator Demo(int num)
  21.     {
  22.         print("先执行的");
  23.         yield return new WaitForSeconds(3.0f);  //等待一秒执行
  24.         print("等待一秒执行的");
  25.         yield return null;                      //下一帧继续执行
  26.         print("最后执行的");
  27.     }
  28.     //协程可以做动画
  29.     public IEnumerator Demo2()
  30.     {
  31.         while (true)
  32.         {
  33.             //暂停0.1秒
  34.             yield return new WaitForSeconds(0.1f);        //等待0.1秒执行旋转
  35.             transform.Rotate(new Vector3(5,0,0));    //使用transform的旋转工具,每0.1秒转5°
  36.         }
  37.        
  38.     }
  39.       public IEnumerator Demo3()
  40.     {
  41.         transform.position = new Vector3(10,10,10);
  42.         yield return Demo2();                       //使用类型可以返回另一个协程,此时执行完成坐标后直接返回到Demo2
  43.     }
  44.      public IEnumerator Demo4()
  45.     {
  46.       //5s之后取消协程
  47.       yield return new WaitForSeconds(5);
  48.      
  49.       StopAllCoroutines();  //取消全部
  50.     }
  51. }

7:常用时间工具函数和数学工具函数

时间工具函数:

Time.time:表示从游戏运行到现在的时间,会随着游戏的暂停而停止计算

Time.deltaTime:表示从上一帧到当前帧的时间,以秒为单位

Time.realtimeSinceStartup:表示从游戏开始后的总时间,即使暂停也会增加,也就是现实时间

Time.timeScale:时间缩放,默认值为1,如果设置<1,表示时间减慢,如果>1表示时间加快,0表示游戏暂停。

  1. Time.timeScale = 0;  //游戏时间一直为0,而真实的时间会一直继续
  2.         Time.timeScale =3;     //时间加快
  3. private void Update()
  4.     {
  5.         //时间工具类
  6.         //每帧上升0.01m
  7.         transform.Translate(new Vector3(0,0.01f,0));
  8.        
  9.         //每秒上升0.01m,方向×速度×一帧花费的时间,用来解除不同帧率电脑的反应时间问题
  10.         transform.Translate(new Vector3(0,0.01f,0)*1* Time.deltaTime);
  11.         print("游戏时间"+Time.time);
  12.         print("帧时间"+Time.deltaTime);
  13.         print("真实时间"+Time.realtimeSinceStartup);
  14.         print(Time.time);   //游戏运行时间
  15.         print(Time.deltaTime);  //从上一帧到当前帧的时间
  16.     }

数学工具类函数:

Mathf.Abs(int num):返回绝对值

Mathf.Max(int a,int ,b):返回更大的值

Mathf.Min(int a,int ,b):返回更小的值

Mathf.Round(2.5f):返回四舍五入后得到的值

Mathf.Ceil(2.5f):返回向上取整的值

Mathf.Floor(2.5f):返回向下取整的值

Random.Range(0,5):返回随机值

  (1)如果是int重载:返回0-4的随机值,包含0,不包含5

  (2)如果是float重载,返回0-5的随机值,包含0且包含5

  1. int num1 =Mathf.Abs(-6);//绝对值
  2.         int num2 =Mathf.Max(1,2,3);//最大值
  3.         int num3 =Mathf.Min(1,2,3);//最小值
  4.         float num4 =Mathf.Round(2.5f);//四舍五入
  5.         float num5 =Mathf.Ceil(2.4f);//向上取整
  6.         float num6 =Mathf.Floor(2.4f);//向下取整
  7. int num =Random.Range(0,5);   //会返回0-4,包含左边,不包含右边
  8.         print(num);
  9.         float num1=Random.Range(0,5.0f); //两边都会返回
  10.         print(num1);

二、单例模式和静态模式

1:单例模式

某些类的实例化方式和其他类有所不同,大多数的类针对属性集和行为定义了模板,并可在场景中多次实例化为GameObject,而有些类则必须作为单一实体存在,比如GameManager、HighScoreManager、AudioManager、SaveGameManager,它们任何时候都只能包含一个类的实例,不然会混淆对象含义,此类对象就称作单例对象

使用GameManger来举例,实际GameManger负责游戏中的全部高层功能项,比如游戏是否处于暂停状态,是否满足胜利条件等

单例的创建和使用过程如下:

  1. using UnityEngine;
  2. usaing System.Collections;
  3. public class GameManager:MonoBehaviour
  4. {
  5. public static GameManager Instance //创建单例
  6. {
  7. get
  8. {
  9. return instance;
  10. }
  11. }
  12. public int HighScore=0;
  13. public bool IsPaused=false;
  14. public bool InputAllowed=true;
  15. }
  16. void Awake()
  17. {
  18. if(instance)
  19. {
  20. DestroyImmediate(gameObject)
  21. return; //对实例变量进行检测,可确定内存中是否存在现有的实例,如果存在,则删除,保证其唯一性
  22. }
  23. instance= this; /让此单例激活并唯一
  24. DontDestroyOnLoad(gameObject); //让此类对象在场景中持久存在
  25. }

*GameManager类使用了Awake()而非Start(),Start是首帧调用,而Awake是对象创建时开始调用,如果GameObjectD启动了禁用状态下的场景,则Start函数不会被调用,直到该对象处于活动状态,对于默认条件下处于活动状态下的对象,Start函数在场景开始时被调用,且位于Awake之后

GameManager的全局静态Instance属性的最大优势在于它可以直接访问任何脚本文件,且无需使用到任何局部变量或对象引用

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/140682
推荐阅读
相关标签
  

闽ICP备14008679号