Static Types
Static Types: use the keyword static. Static information can be thought of as stuck in the program’s memory for the life of the program.static类型保证了这个物体的信息在整个游戏的进行中不会销毁,即使物体本身已经被销毁。信息通过相关类获取的, 和脚本依附的物体无关
public class Score : MonoBehaviour
{
public static int score;
}
public class StaticTest : MonoBehaviour
{
private Score _score;
// Start is called before the first frame update
void Start()
{
//_score = GameObject.Find("ScoreKeeper").GetComponent<Score>(); // Do not use this
}
// Update is called once per frame
void Update()
{
if(Input.GetKeyDown(KeyCode.Space)){
// _score.score += 10; // Do not use this
Score.score += 10; //correct way
}
}
}
static允许我们在类的层次上取获取信息,因为这一类型的数据是无限期存储在记忆体中,我们不需要通过一个实例来获取信息
另外一个要注意的是,在static函数中使用的变量也要是static的
KEY:(in part 2 of this chapter)
- 在游戏界面上显示文本等:
- 创建画布:Hierarchy右键->UI->Canvas
- 创建文本:Hierarchy右键->UI->Text (图片什么的同理
- 游戏背景:在Main Camera中Clear Flag进行设置 默认是sky box 想要纯颜色就切换成Solid Color
OnEnable() / OnDisable()
:Make GameObject become inabled or disabled(when u destory a GameObject, it’s not longer enabled
讲一下part2这边的代码吧 这组代码实现的功能很简单 生成物体并在一定时间内销毁 在界面显示当前存在的物体数量 创建两个GameObject Spawn_Manager和UI_Manager分别用于生成enemy和UI界面设置 以及生成对象预制件Enemy
/* SpawnManager.cs*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpawnManager : MonoBehaviour
{
public GameObject enemyPrefab;
public static int enemyCount; // will be used in whole game
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
//instantiate
if(Input.GetKeyDown(KeyCode.Space)){
Instantiate(enemyPrefab);
}
}
}
/* UIManager.cs*/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; // this package reference to UI
public class UIManager : MonoBehaviour
{
// Start is called before the first frame update
public Text activateEnemiesText; // get text info
public void UpdateEnemyCount(){
activateEnemiesText.text = "Active Enemies: " + SpawnManager.enemyCount;
}
}
/* Enemy.cs */
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// when enemy instantiate, EnemyCount incre; if destory, decre
public class Enemy : MonoBehaviour
{
private UIManager _ui;
public void OnEnable()
{
SpawnManager.enemyCount++;
_ui = GameObject.Find("UI_Manager").GetComponent<UIManager>(); //Script is also a component
_ui.UpdateEnemyCount(); // when the enemyCount change, call this function to update the number on the screen immediately
Die();
}
public void OnDisable()
{
// when this object destory, it become Disabled status
SpawnManager.enemyCount--;
_ui.UpdateEnemyCount();
}
void Die(){
Destroy(this.gameObject, Random.Range(2, 6)); //destory the obj after 2-6s(random)
}
}
Instance Members vs. Static Members
Static members live for the life of the program, whereas instance members have instances of themselves. When we create a custom item class, we’re creating instances of those items. When u have a static variable within a traditional class, that variable is shared amongst all these instance.
举个栗子
public class InsItem{
public string name;
public int itemID;
public static int itemCount;
public InsItem(){
itemCount++; // when a instance create, itemCount++
}
}
public class InstanceTest : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
InsItem sword = new InsItem();
InsItem bread = new InsItem();
Debug.Log(InsItem.itemCount); //2
}
// Update is called once per frame
void Update()
{
}
}
对于sword和bread这两个实例, 我们可以很容易通过sword.name
, sword.itemID
获取name和itemID属性并进行改变,但是我们却无法通过进行sword.itemCount
操作来获取。因为这些实例他们共享itemCount
这一变量。itemCount
是在整个程序中无限期存在的,无论是否有一个InsItem
实例。如果要获取这个静态变量,我们只能通过InsItem.itemCount
来获取。
Static members are shared across all the instance, whereas instance members are created as copies. 以这个例子来说, name
和itemID
在一个InsItem
实例被创建时就被拷贝一份,而itemCount
是一个共享数据。
[场景]:多人游戏(multiplayer games)的在线人数统计, 当玩家上线时然后会显示当前世界有多少人在线。把上面那个InsItem类改一改叫做Player的类好了(其实没差 , 每当玩家上线时就创建一个Player实例然后人数增加。 (提问:玩家下线时,当前世界人数如何减少\
Utility Helper Classes
Utility Classes are basically helper methods that you have created so that u can ideally streamline your development process.
一般情况下 你的UtilityClass不需要继承MonoBehaviour 它将会是一个static class并存储一堆static methods方便调用
KEY of Utility Class:
- 不继承MonoBehaviour
- 里面的变量和方法都是static的(因为他是static class
来看一个代码 先把涉及到的函数做个解释
GameObject.CreatePrimitive(PrimitiveType)
: 创建一个原始的GameObject(包含了mesh renderer和collider),括号内是这个GObj的类型,比如cube,cylinder之类的
在调用这些函数时直接在类的层次上进行调用 就不需要再创一个GameObject来存储这些操作
public static class UtilityClass
{
public static void CreateObject()
{
// create a new primitive cube
GameObject.CreatePrimitive(PrimitiveType.Cube);
}
public static void SetPositionToZero(GameObject obj)
{
// change position of obj
obj.transform.position = Vector3.zero;
}
}
Initializing Static Members with a Static Constructor
比如说我们现在有一个类,里面有普通的变量也有静态变量。当我们要初始化这个类里面的值时,我们通常就是通过构造函数来实现,来初始化一个实例。那么对于static变量,我们可以用static constructor。这是为了保证当我们在创建这个类的实例前,我们的这个静态变量已经被初始化(因为这是一个在实例中共享的变量)。
public class Employee
{
public string first, last;
public int employeeID;
public int salary;
public static string company;
public Employee(){
Debug.Log("Initialize Instance Members");
}
// to make sure "company" is assigned before create a employee
static Employee(){
company = "RinMZK";
Debug.Log("Initialize Static Members");
}
}
public class TrackEmployee : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
Employee em1 = new Employee();
Employee em2 = new Employee();
}
// Update is called once per frame
void Update()
{
}
}
我们可以来看看它的执行顺序
很明显是先执行static constructor将静态变量初始化然后再创建实例。我们可以注意到的是,static constructor只执行一次,无论创建了多少实例。