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;
}
}
- 事件推荐设置为静态,这样在其他类中订阅事件就不必实例化
这篇中级Unity教程涵盖了关键编程概念,包括Properties、三元运算符、静态成员、方法重载、泛型、继承、多态、成员隐藏、重写、接口、扩展方法、命名空间、列表和字典、协程、四元数、Delegate、Attributes及事件。通过这些概念,你可以更好地理解和应用Unity的脚本编写。
&spm=1001.2101.3001.5002&articleId=50726096&d=1&t=3&u=bf5311d1ca6b452ea90f879cd2b69403)
1668

被折叠的 条评论
为什么被折叠?



