Learn Unity - Scripts(中级教程)

来源:互联网 发布:广告优化师 编辑:程序博客网 时间:2024/05/22 15:01

Properties

如何创建Properties去访问类中的私有成员变量

这个方法一般用于隐藏类中的变量而又开放出读取或设置的权限,见示例:

using UnityEngine;using System.Collections;public class Player{    //Member variables can be referred to as fields.    private int experience;    //Experience is a basic property    public int Experience    {        get        {            //Some other code            return experience;        }        set        {            //Some other code            experience = value;        }    }    //Level is a property that converts experience    //points into the leve of a player automatically    public int Level    {        get        {            return experience / 1000;        }        set        {            experience = value * 1000;        }    }    //This is an example of an auto-implemented    //property    public int Health{ get; set;}}
using UnityEngine;using System.Collections;public class Game : MonoBehaviour {    void Start ()     {        Player myPlayer = new Player();        //Properties can be used just like variables        myPlayer.Experience = 5;        int x = myPlayer.Experience;    }}

三元运算符(*?:)

如何用三元运算符快速建立一个if-else语句

例:

message = health > 0 ? "Player is Alive" : "Player is Dead";

?前面是判定条件,?和:中间是条件为true的结果,:后面是条件为false的结果

静态(Static)

可以设置类,函数,属性为静态,静态即不能被实例化,唯一

重载方法(Method Overloading)

using UnityEngine;using System.Collections;public class SomeClass{    //The first Add method has a signature of    //"Add(int, int)". This signature must be unique.    public int Add(int num1, int num2)    {        return num1 + num2;    }    //The second Add method has a sugnature of    //"Add(string, string)". Again, this must be unique.    public string Add(string str1, string str2)    {        return str1 + str2;    }}

重写方法,函数名相同而传入参数不同,方法会寻找最匹配类型的方法执行,若找不到,则返回错误

泛型(Generics)

泛型方法

当然可以不止是T,也可以是U,V等多个范类型,若需要规定类型的范围,可以如下一样添加where语句来规定

using UnityEngine;using System.Collections;public class SomeClass {    //Here is a generic method. Notice the generic    //type 'T'. This 'T' will be replaced at runtime    //with an actual type.     public T GenericMethod<T>(T param) where T : int    {        return param;    }}

泛型类

using UnityEngine;using System.Collections;//Here is a generic class. Notice the generic type 'T'.//'T' will be replaced with an actual type, as will also //instances of the type 'T' used in the class.public class GenericClass <T>{    T item;    public void UpdateItem(T newItem)    {        item = newItem;    }}

继承(Inheritance)

面向对象思想编程

父类

using UnityEngine;using System.Collections;//This is the base class which is//also known as the Parent class.public class Fruit {    public string color;    //This is the first constructor for the Fruit class    //and is not inherited by any derived classes.    public Fruit()    {        color = "orange";        Debug.Log("1st Fruit Constructor Called");    }    //This is the second constructor for the Fruit class    //and is not inherited by any derived classes.    public Fruit(string newColor)    {        color = newColor;        Debug.Log("2nd Fruit Constructor Called");    }    public void Chop()    {        Debug.Log("The " + color + " fruit has been chopped.");         }    public void SayHello()    {        Debug.Log("Hello, I am a fruit.");    }}

子类

using UnityEngine;using System.Collections;//This is the derived class whis is//also know as the Child class.public class Apple : Fruit {    //This is the first constructor for the Apple class.    //It calls the parent constructor immediately, even    //before it runs.    public Apple()    {        //Notice how Apple has access to the public variable        //color, which is a part of the parent Fruit class.        color = "red";        Debug.Log("1st Apple Constructor Called");    }    //This is the second constructor for the Apple class.    //It specifies which parent constructor will be called    //using the "base" keyword.    public Apple(string newColor) : base(newColor)    {        //Notice how this constructor doesn't set the color        //since the base constructor sets the color that        //is passed as an argument.        Debug.Log("2nd Apple Constructor Called");    }}
  • 子类会继承父类public和protect的属性和方法,而对于private则不行
  • 子类构造函数使用base关键字来说明使用了父类哪个构造函数,使用用类似于java的super,因为C#不支持多继承,父类用base即可,C++支持多继承,所以要写父类名字说明,也是两者区别之一。

多态(Polymorphism)

using UnityEngine;using System.Collections;public class Fruit {    public Fruit()    {        Debug.Log("1st Fruit Constructor Called");    }    public void Chop()    {        Debug.Log("The fruit has been chopped.");         }    public void SayHello()    {        Debug.Log("Hello, I am a fruit.");    }}
using UnityEngine;using System.Collections;public class Apple : Fruit {    public Apple()    {        Debug.Log("1st Apple Constructor Called");    }    //Apple has its own version of Chop() and SayHello().     //When running the scripts, notice when Fruit's version    //of these methods are called and when Apple's version    //of these methods are called.    //In this example, the "new" keyword is used to supress    //warnings from Unity while not overriding the methods    //in the Apple class.    public new void Chop()    {        Debug.Log("The apple has been chopped.");         }    public new void SayHello()    {        Debug.Log("Hello, I am an apple.");    }}
using UnityEngine;using System.Collections;public class FruitSalad : MonoBehaviour{    void Start ()     {        //Notice here how the variable "myFruit" is of type        //Fruit but is being assigned a reference to an Apple. This        //works because of Polymorphism. Since an Apple is a Fruit,        //this works just fine. While the Apple reference is stored        //in a Fruit variable, it can only be used like a Fruit        Fruit myFruit = new Apple();        myFruit.SayHello();        myFruit.Chop();        //This is called downcasting. The variable "myFruit" which is         //of type Fruit, actually contains a reference to an Apple. Therefore,        //it can safely be turned back into an Apple variable. This allows        //it to be used like an Apple, where before it could only be used        //like a Fruit.        Apple myApple = (Apple)myFruit;        myApple.SayHello();        myApple.Chop();     }}
  • new关键字是当子类没有重写父类方法的时候提供来自unity的警告
  • 当子类引用储存在父类变量中,只能像父类一样使用,当强制安全降级到子类变量中,就可以像子类一样使用

成员隐藏(Member Hiding)

using UnityEngine;using System.Collections;public class Humanoid{    //Base version of the Yell method    public void Yell()    {        Debug.Log ("Humanoid version of the Yell() method");    }}
using UnityEngine;using System.Collections;public class Enemy : Humanoid{    //This hides the Humanoid version.    new public void Yell()    {        Debug.Log ("Enemy version of the Yell() method");    }}
using UnityEngine;using System.Collections;public class WarBand : MonoBehaviour {    void Start ()     {        Humanoid human = new Humanoid();        Humanoid enemy = new Enemy();        //Notice how each Humanoid variable contains        //a reference to a different class in the        //inheritance hierarchy, yet each of them        //calls the Humanoid Yell() method.        human.Yell();        enemy.Yell();    }}
  • new关键字显式隐藏从父类继承来的成员,不然unity会有警告

重写/覆盖(Overriding)

using UnityEngine;using System.Collections;public class Fruit {    public Fruit ()    {        Debug.Log("1st Fruit Constructor Called");    }    //These methods are virtual and thus can be overriden    //in child classes    public virtual void Chop ()    {        Debug.Log("The fruit has been chopped.");         }    public virtual void SayHello ()    {        Debug.Log("Hello, I am a fruit.");    }}
using UnityEngine;using System.Collections;public class Apple : Fruit {    public Apple ()    {        Debug.Log("1st Apple Constructor Called");    }    //These methods are overrides and therefore    //can override any virtual methods in the parent    //class.    public override void Chop ()    {        base.Chop();        Debug.Log("The apple has been chopped.");         }    public override void SayHello ()    {        base.SayHello();        Debug.Log("Hello, I am an apple.");    }}
using UnityEngine;using System.Collections;public class FruitSalad : MonoBehaviour {       void Start ()     {        Apple myApple = new Apple();        //Notice that the Apple version of the methods        //override the fruit versions. Also notice that        //since the Apple versions call the Fruit version with        //the "base" keyword, both are called.        myApple.SayHello();        myApple.Chop();         //Overriding is also useful in a polymorphic situation.        //Since the methods of the Fruit class are "virtual" and        //the methods of the Apple class are "override", when we         //upcast an Apple into a Fruit, the Apple version of the         //Methods are used.        Fruit myFruit = new Apple();        myFruit.SayHello();        myFruit.Chop();    }}
  • 当子类重写了父类后,子类需要通过base关键字来调用父类
  • 重写也用于多态,父类方法有virtual关键字时,子类相同方法添加override关键字,这样,即使子类引用上升了父类变量,依旧会使用子类的方法

接口(Interfaces)

using UnityEngine;using System.Collections;//This is a basic interface with a single required//method.public interface IKillable{    void Kill();}//This is a generic interface where T is a placeholder//for a data type that will be provided by the //implementing class.public interface IDamageable<T>{    void Damage(T damageTaken);}
using UnityEngine;using System.Collections;public class Avatar : MonoBehaviour, IKillable, IDamageable<float>{    //The required method of the IKillable interface    public void Kill()    {        //Do something fun    }    //The required method of the IDamageable interface    public void Damage(float damageTaken)    {        //Do something fun    }}
  • 接口不能实例化,只能进行简单的定义
  • 继承与接口类似,至于为什么不使用继承而使用接口,区别就是C#支持实现多个接口而不支持继承多个父类,而继承与接口使用的方向也不同,继承的父类大多指的是物体,而接口大多指的是状态

扩展方法(extension methods)

using UnityEngine;using System.Collections;//It is common to create a class to contain all of your//extension methods. This class must be static.public static class ExtensionMethods{    //Even though they are used like normal methods, extension    //methods must be declared static. Notice that the first    //parameter has the 'this' keyword followed by a Transform    //variable. This variable denotes which class the extension    //method becomes a part of.    public static void ResetTransformation(this Transform trans)    {        trans.position = Vector3.zero;        trans.localRotation = Quaternion.identity;        trans.localScale = new Vector3(1, 1, 1);    }}
using UnityEngine;using System.Collections;//It is common to create a class to contain all of your//extension methods. This class must be static.public static class ExtensionMethods{    //Even though they are used like normal methods, extension    //methods must be declared static. Notice that the first    //parameter has the 'this' keyword followed by a Transform    //variable. This variable denotes which class the extension    //method becomes a part of.    public static void ResetTransformation(this Transform trans)    {        trans.position = Vector3.zero;        trans.localRotation = Quaternion.identity;        trans.localScale = new Vector3(1, 1, 1);    }}
  • 扩展方法方便为已有的类中添加方法,其中有三个条件:
    1.静态类
    2.静态方法
    3.静态方法的第一个参数带有this关键字

命名空间(Namespaces)

using UnityEngine;using System.Collections;namespace SampleNamespace{    public class SomeClass : MonoBehaviour     {        void Start ()         {        }    }}
  • using也就是使用哪些命名空间里,方便使用里面类或方法,设置命名空间为了避免同名方法的混淆

列表和字典(Lists and Dictionaries)

using UnityEngine;using System.Collections;using System; //This allows the IComparable Interface//This is the class you will be storing//in the different collections. In order to use//a collection's Sort() method, this class needs to//implement the IComparable interface.public class BadGuy : IComparable<BadGuy>{    public string name;    public int power;    public BadGuy(string newName, int newPower)    {        name = newName;        power = newPower;    }    //This method is required by the IComparable    //interface.     public int CompareTo(BadGuy other)    {        if(other == null)        {            return 1;        }        //Return the difference in power.        return power - other.power;    }}
using UnityEngine;using System.Collections;using System.Collections.Generic;public class SomeClass : MonoBehaviour{    void Start ()     {        //This is how you create a list. Notice how the type        //is specified in the angle brackets (< >).        List<BadGuy> badguys = new List<BadGuy>();        //Here you add 3 BadGuys to the List        badguys.Add( new BadGuy("Harvey", 50));        badguys.Add( new BadGuy("Magneto", 100));        badguys.Add( new BadGuy("Pip", 5));        badguys.Sort();        foreach(BadGuy guy in badguys)        {            print (guy.name + " " + guy.power);        }        //This clears out the list so that it is        //empty.        badguys.Clear();    }}
using UnityEngine;using System.Collections;using System.Collections.Generic;public class SomeOtherClass : MonoBehaviour {    void Start ()    {        //This is how you create a Dictionary. Notice how this takes        //two generic terms. In this case you are using a string and a        //BadGuy as your two values.        Dictionary<string, BadGuy> badguys = new Dictionary<string, BadGuy>();        BadGuy bg1 = new BadGuy("Harvey", 50);        BadGuy bg2 = new BadGuy("Magneto", 100);        //You can place variables into the Dictionary with the        //Add() method.        badguys.Add("gangster", bg1);        badguys.Add("mutant", bg2);        BadGuy magneto = badguys["mutant"];        BadGuy temp = null;        //This is a safer, but slow, method of accessing        //values in a dictionary.        if(badguys.TryGetValue("birds", out temp))        {            //success!        }        else        {            //failure!        }    }}
  • List跟C++中List相似,而Dictionary是键值对的形式,跟map相似,以上是相应的使用范例

协程(Coroutines)

using UnityEngine;using System.Collections;public class CoroutinesExample : MonoBehaviour{    public float smoothing = 1f;    public Transform target;    void Start ()    {        StartCoroutine(MyCoroutine(target));    }    IEnumerator MyCoroutine (Transform target)    {        while(Vector3.Distance(transform.position, target.position) > 0.05f)        {            transform.position = Vector3.Lerp(transform.position, target.position, smoothing * Time.deltaTime);            yield return null;        }        print("Reached the target.");        yield return new WaitForSeconds(3f);        print("MyCoroutine is now finished.");    }}
  • StartCoroutine开启协程
  • StopCoroutine停止协程
  • 协程方法要返回IEnumerator接口类型
  • yield跟return类似,不过是等待一定延迟后继续执行

四元数(quaternion)

Quaternion是Unity中处理旋转的常用类,下面是一些代码例子

using UnityEngine;using System.Collections;public class GravityScript : MonoBehaviour {    public Transform target;    void Update ()     {        Vector3 relativePos = (target.position + new Vector3(0, 1.5f, 0)) - transform.position;        Quaternion rotation = Quaternion.LookRotation(relativePos);        Quaternion current = transform.localRotation;        transform.localRotation = Quaternion.Slerp(current, rotation, Time.deltaTime);        transform.Translate(0, 0, 3 * Time.deltaTime);    }}
  • Quaternion.LookRotation得出朝向目标的旋转
  • Quaternion.Slerp现有旋转角度转到目标角度取插值,使平滑

Delegate

delegate就是方法的容器

using UnityEngine;using System.Collections;public class DelegateScript : MonoBehaviour {       delegate void MyDelegate(int num);    MyDelegate myDelegate;    void Start ()     {        myDelegate = PrintNum;        myDelegate(50);        myDelegate = DoubleNum;        myDelegate(50);    }    void PrintNum(int num)    {        print ("Print Num: " + num);    }    void DoubleNum(int num)    {        print ("Double Num: " + num * 2);    }}
using UnityEngine;using System.Collections;public class MulticastScript : MonoBehaviour {    delegate void MultiDelegate();    MultiDelegate myMultiDelegate;    void Start ()     {        myMultiDelegate += PowerUp;        myMultiDelegate += TurnRed;        if(myMultiDelegate != null)        {            myMultiDelegate();        }    }    void PowerUp()    {        print ("Orb is powering up!");    }    void TurnRed()    {        renderer.material.color = Color.red;    }}
  • delegate容器可以存一个或多个同一类型的方法,方便同时调用不同的方法,使用之前最好判断下是否为null

Attributes

using UnityEngine;using System.Collections;public class SpinScript : MonoBehaviour {    [Range(-100, 100)] public int speed = 0;    void Update ()     {        transform.Rotate(new Vector3(0, speed * Time.deltaTime, 0));    }}
  • 此处的attribute就是限定了speed的范围,在inspector界面也只能在此范围内调节,更多attribute请参考官方文档

事件(Events)

events也是主要靠delegate实现委托的,不过添加event关键字增强了代码的安全性,使其他类只能订阅或者取消订阅事件,而不能执行或者复写事件

using UnityEngine;using System.Collections;public class EventManager : MonoBehaviour {    public delegate void ClickAction();    public static event ClickAction OnClicked;    void OnGUI()    {        if(GUI.Button(new Rect(Screen.width / 2 - 50, 5, 100, 30), "Click"))        {            if(OnClicked != null)                OnClicked();        }    }}
using UnityEngine;using System.Collections;public class TeleportScript : MonoBehaviour {    void OnEnable()    {        EventManager.OnClicked += Teleport;    }    void OnDisable()    {        EventManager.OnClicked -= Teleport;    }    void Teleport()    {        Vector3 pos = transform.position;        pos.y = Random.Range(1.0f, 3.0f);        transform.position = pos;    }}
  • 事件推荐设置为静态,这样在其他类中订阅事件就不必实例化
0 0
原创粉丝点击