当前位置:   article > 正文

C# In Unity 中级编程_using unityengine;

using unityengine;

中级教程

  官方中文教程请戳

1.创建属性

  如何在类外访问类内的成员变量?将变量声明为 p u b l i c public public——这是可行的,但是不是最好的做法——使用属性。
  属性本身可以当作变量,并且可以封装成员变量(也称字段)。通过这种封装,我们可以更好的控制字段的访问时间和访问方式。

using UnityEngine;
using System.Collections;

public class Player
{
    //成员变量可以称为
    //字段。
    private int experience;

    //Experience 是一个基本属性
    public int Experience
    {
        get
        {
            //其他一些代码
            return experience;
        }
        set
        {
            //其他一些代码
            experience = value;
        }
    }

    //Level 是一个将经验值自动转换为
    //玩家等级的属性
    public int Level
    {
        get
        {
            return experience / 1000;
        }
        set
        {
            experience = value * 1000;
        }
    }

    //这是一个自动实现的属性的
    //示例
    public int Health{ get; set;}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
using UnityEngine;
using System.Collections;

public class Game : MonoBehaviour 
{
    void Start () 
    {
        Player myPlayer = new Player();

        //属性可以像变量一样使用
        myPlayer.Experience = 5;
        int x = myPlayer.Experience;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

  相较于 p u b l i c public public,属性有什么过人之处吗?当然,通过省略 g e t get get s e t set set,我们可以将字段变成只写或只读;我们也可以认为 g e t 、 s e t get、set getset是两个函数,在其内部可以运行其他代码或者调用其他函数,正如上例的 L e v e l Level Level所示。

3.静态

  静态成员可直接通过类访问而无需实例化对象。静态成员是这个类的所有实例所共有的,非静态成员是这个类的每个实例所私有的。

using UnityEngine;
using System.Collections;

public class Enemy
{
    //静态变量是在类的所有实例之间
    //共享的变量。
    public static int enemyCount = 0;

    public Enemy()
    {
        //通过递增静态变量了解
        //已创建此类的多少个对象。
        enemyCount++;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
using UnityEngine;
using System.Collections;

public class Game
{
    void Start () 
    {
        Enemy enemy1 = new Enemy();
        Enemy enemy2 = new Enemy();
        Enemy enemy3 = new Enemy();

        //可以使用类名和点运算符
        //来访问静态变量。
        int x = Enemy.enemyCount;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

  静态方法无法访问非静态成员变量。

using UnityEngine;
using System.Collections;

public static class Utilities 
{
    //可以在没有类对象的情况下调用
    //静态方法。请注意,静态方法无法访问
    //非静态成员变量。
    public static int Add(int num1, int num2)
    {
        return num1 + num2;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
using UnityEngine;
using System.Collections;

public class UtilitiesExample : MonoBehaviour 
{
    void Start()
    {
        //可以使用类名和点运算符
        //来访问静态方法。
        int x = Utilities.Add (5, 6);
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

  如果某个类的所有成员和方法都是静态的,那么可以把这个类声明称静态类。静态类无法创建实例。

10.接口

  接口可被视为关于功能的协定。实现接口的任何类必须拥有其所有方法和属性。接口本身不是类,不能有任何实例。
在这里插入图片描述

using UnityEngine;
using System.Collections;

//这是只有一个必需方法的基本
//接口。
public interface IKillable
{
    void Kill();
}

//这是一个通用接口,其中 T 是
//将由实现类提供的数据类型的
//占位符。
public interface IDamageable<T>
{
    void Damage(T damageTaken);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
using UnityEngine;
using System.Collections;

public class Avatar : MonoBehaviour, IKillable, IDamageable<float>
{
    //IKillable 接口的必需方法
    public void Kill()
    {
        //执行一些有趣操作
    }

    //IDamageable 接口的必需方法
    public void Damage(float damageTaken)
    {
        //执行一些有趣操作
    }
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

  接口的主要优势是允许跨多个类定义通用功能。

11.扩展方法

  通过扩展方法可以向类型添加功能,而不需要修改原类型或者继承。它非常适用于需要向类添加功能而不能编辑类的情况,比如 u n i t y unity unity中的一些内置类。

using UnityEngine;
using System.Collections;

//创建一个包含所有扩展方法的类
//是很常见的做法。此类必须是静态类。
public static class ExtensionMethods
{
    //扩展方法即使像普通方法一样使用,
    //也必须声明为静态。请注意,第一个
    //参数具有“this”关键字,后跟一个 Transform
    //变量。此变量表示扩展方法会成为
    //哪个类的一部分。
    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
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
using UnityEngine;
using System.Collections;

public class SomeClass : MonoBehaviour 
{
    void Start () {
        //请注意,即使方法声明中
        //有一个参数,也不会将任何参数传递给
        //此扩展方法。调用此方法的
        //Transform 对象会自动作为
        //第一个参数传入。
        transform.ResetTransformation();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

14.协程

  协同程序可被视为按时间间隔执行的函数,这类函数与特殊语句 y i e l d yield yield搭配使用。 y i e l d yield yield语句从函数中返回代码执行,然后当函数继续时,从上次停止的地方开始执行。强烈推荐看一下这一节对应的视频。

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.");
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

16.委托

  委托可被简单的视作函数的容器,可以进行传递或像变量一样被使用。

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);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
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;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

17.属性

   [ E x e c u t e I n E d i t M o d e ] [ExecuteInEditMode] [ExecuteInEditMode]可以让该脚本在编辑模式下运行。但是请注意,在编辑模式下所做的改动是真实有效的!

using UnityEngine;
using System.Collections;

[ExecuteInEditMode]
public class ColorScript : MonoBehaviour 
{
    void Start()
    {
        renderer.sharedMaterial.color = Color.red;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

18.事件

  事件是一种特殊委托,非常适用于想要提醒其他类发生了某个事件。事实上,事件函数和公共多播委托非常类似。事件可被视为广播系统,对事件感兴趣的任何类都可以将方法订阅到事件,发生这个特定事件时,比如点击按钮、充能或玩家受伤,我们会调用事件进而调用已订阅的类的方法。

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();
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
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;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
using UnityEngine;
using System.Collections;

public class TurnColorScript : MonoBehaviour 
{
    void OnEnable()
    {
        EventManager.OnClicked += TurnColor;
    }


    void OnDisable()
    {
        EventManager.OnClicked -= TurnColor;
    }


    void TurnColor()
    {
        Color col = new Color(Random.value, Random.value, Random.value);
        renderer.material.color = col;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

  取消事件的订阅是非常重要的,不然可能导致内存泄漏或游戏出错等问题。从上面的例子我们可以看到, E v e n t M a n a g e r EventManager EventManager只需要留意事件本身和事件触发器; T e l e p o r t S c r i p t TeleportScript TeleportScript T u r n C o l o r S c r i p t TurnColorScript TurnColorScript也不需要相互了解。
  但是不难发现上面的例子利用公共委托变量也可以实现,那么为什么要使用事件呢?事件具有内在安全性,而委托变量没有。通过事件,其他类只能订阅和退订;如果改用公共委托变量,其他类可能会调用或覆盖公共委托变量。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/140714
推荐阅读
相关标签
  

闽ICP备14008679号