一.创建属性
创建一个属性,在属性后的括号内创建访问器
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;}
}
在另一个文件中创建Game类:
Player中的属性,在Game中可以当成变量使用
using UnityEngine;
using System.Collections;
public class Game : MonoBehaviour
{
void Start ()
{
Player myPlayer = new Player();
//属性可以像变量一样使用
myPlayer.Experience = 5;
int x = myPlayer.Experience;
}
}
为什么在有public和private的情况下,仍然建议使用属性呢?
因为使用属性可以使类内部封装的数据得以安全的被访问和修改。比如我们不希望类内部数据受到类外部的随意修改,使用了private,但是有时外部的代码又需要用到类内部的数据,这时通过设置属性,就可以为外部代码提供一个安全,合理的访问途径。
通俗点说就是,A可以让B进自己家里,但是B必须遵循A的命令,拿什么,怎么拿,都得听A的,而不是放B进来随意胡闹,也不是完全禁止B进来。
二.静态(static)
1.静态变量
一般来说,一个类的各个对象拥有相同变量,但是每个变量有自己的值。对于静态变量,类中的每个对象拥有相同的变量和相同的值。
比如想知道此类创建了多少个对象:
using UnityEngine;
using System.Collections;
public class Enemy
{
//静态变量是在类的所有实例之间
//共享的变量。
public static int enemyCount = 0;
public Enemy()
{
//通过递增静态变量了解
//已创建此类的多少个对象。
enemyCount++;
}
}
2.静态类
在静态类中编写的方法,可以在另一个类中通过静态类的类名和点运算符来调用
静态类:
using UnityEngine;
using System.Collections;
public static class Utilities
{
//可以在没有类对象的情况下调用
//静态方法。请注意,静态方法无法访问
//非静态成员变量。
public static int Add(int num1, int num2)
{
return num1 + num2;
}
}
在非静态类中调用静态类中的方法:
using UnityEngine;
using System.Collections;
public class UtilitiesExample : MonoBehaviour
{
void Start()
{
//可以使用类名和点运算符
//来访问静态方法。
int x = Utilities.Add (5, 6);
}
}
三.覆盖
若子类存在与父类同名方法,则调用此方法时,将调用父类的版本。因为是父类的声明,子类隐式向外转换为父类。
爷类
using UnityEngine;
using System.Collections;
public class Humanoid
{
//Yell 方法的基版本
public void Yell()
{
Debug.Log ("Humanoid version of the Yell() method");
}
}
父类
using UnityEngine;
using System.Collections;
public class Enemy : Humanoid
{
//这会隐藏 Humanoid 版本。
new public void Yell()
{
Debug.Log ("Enemy version of the Yell() method");
}
}
子类
using UnityEngine;
using System.Collections;
public class Orc : Enemy
{
//这会隐藏 Enemy 版本。
new public void Yell()
{
Debug.Log ("Orc version of the Yell() method");
}
}
以父类声明的形式实例化,并调用这些方法:
using UnityEngine;
using System.Collections;
public class WarBand : MonoBehaviour
{
void Start ()
{
Humanoid human = new Humanoid();
Humanoid enemy = new Enemy();
Humanoid orc = new Orc();
//注意每个 Humanoid 变量如何包含
//对继承层级视图中
//不同类的引用,但每个变量都
//调用 Humanoid Yell() 方法。
human.Yell();
enemy.Yell();
orc.Yell();
}
}
四.接口
一个类只能继承一个父类,但是可以实现多个接口。接口可以跨多个互不相关的类来定义通用功能。
实现接口:
using UnityEngine;
using System.Collections;
//这是只有一个必需方法的基本接口
public interface IKillable
{
void Kill();
}
//这是一个通用接口,其中 T 是将由实现类提供的数据类型的占位符。
public interface IDamageable<T>
{
void Damage(T damageTaken);
}
实现接口中的方法:
using UnityEngine;
using System.Collections;
//这是只有一个必需方法的基本接口
public interface IKillable
{
void Kill();
}
//这是一个通用接口,其中 T 是将由实现类提供的数据类型的占位符。
public interface IDamageable<T>
{
void Damage(T damageTaken);
}
五.扩展方法
假如我们希望通过一个函数就可以重置Transform中的各个参数,这个函数最理想的位置就是在Transform类中,但是由于我们无法访问Unity内置的Transform的源代码,所以我们可以为其创建扩展。
注意,扩展方法必须放在非泛型,静态类中,扩展方法本身也声明为静态方法。一般会专门创建一个类来包含它们。
using UnityEngine;
using System.Collections;
//创建一个包含所有扩展方法的类是很常见的做法
//此类必须是静态类
public static class ExtensionMethods
{
//扩展方法即使像普通方法一样使用,也必须声明为静态
//注意,第一个参数具有“this”关键字,后跟一个 Transform变量
//此变量表示扩展方法会成为哪个类的一部分
public static void ResetTransformation(this Transform trans)
{
//编写重置Transform的代码
trans.position = Vector3.zero;
trans.localRotation = Quaternion.identity;
trans.localScale = new Vector3(1, 1, 1);
}
}
需要注意的是,尽管扩展方法声明具有参数,但是调用这个函数时不会传递任何参数。调用此方法的Transform对象会自动作为第一个参数传入。
using UnityEngine;
using System.Collections;
public class SomeClass : MonoBehaviour
{
void Start () {
//请注意,即使方法声明中
//有一个参数,也不会将任何参数传递给
//此扩展方法。调用此方法的
//Transform 对象会自动作为
//第一个参数传入。
transform.ResetTransformation();
}
}
五.协程
协程函数可以看成,按时间间隔执行的函数。协程函数通常与yield语句搭配使用。协程函数每次执行都会从上一次停止的地方开始。使用协程可以不用像Update那样每帧都执行一次,提高了效率。
yield语句:
yield return null; | 在下一帧执行后续代码 |
yield break; | 结束协程 |
yield return new WaitForSeconds(0.5f); | 等待固定时间后执行后续代码 |
using UnityEngine;
using System.Collections;
public class CoroutinesExample : MonoBehaviour
{
public float smoothing = 1f;
public Transform target;
void Start ()
{
//开启协程
StartCoroutine(MyCoroutine(target));
}
//返回类型为IEnumerator
//表示函数可以返回实现IEnumerator接口的任意内容
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.");
}
}