Unity之C#学习笔记(11):静态类型 Static

前篇链接:Unity之C#学习笔记(10):接口和多态 Interfaces and Polymorphism

静态类型(Static)用一句话概括就是:在程序运行期间只会被创建一份的通用内容,用关键字static修饰,主要包括静态类、静态变量和静态方法。我们这里主要讨论静态变量和静态方法。这一篇博文给出了比较详细的介绍,可以作为补充:C# 之 static的用法详解

静态变量和方法是类中的成员。与一般的成员变量和方法不同的是,无论我们创建多少个类的对象,静态成员都只会存在一个。换一种说法,静态成员不依赖于类的具体对象。从内存分配角度来说,静态成员的存储位置和非静态成员不同,当创建新对象时,会在堆中为非静态成员新分配空间。而静态成员从最初就存储在其他位置,只会有一个存储空间。

静态成员有一个特性:可以通过类名.变量名(方法名)直接访问。这个特性对于我们在Unity中编程是非常便利的。对于非静态成员,我们要先通过GetComponent获得类的实例,再访问或调用对应的变量或方法,而静态成员则通过类名即可调用。

对于静态方法,因为它不属于任何类的示例,所以不能调用任何非静态的成员。

静态成员可以通过静态构造函数来初始化,我们通过一个Employee雇员类的例子来说明。

public class Employee
{
    public int employeeID;
    public string firstName, lastName;
    public int salary;

    public static string companyName;

    public Employee()
    {
        Debug.Log("Constructor called");
        employeeID = 0;
        lastName = "张";
        firstName = "三";
        salary = 8000;
    }
    static Employee()
    {
        Debug.Log("Static Constructor called");
        companyName = "Tencent";
    } 
}

雇员有一些各不相同个人的信息,还有一个公共的公司名。public Employee()是Employee类的构造函数,而static Employee()就是它的静态构造函数,可以将所有静态成员在这里初始化。我们知道,构造函数会在每次创建一个新的类的对象时被调用。而静态构造函数不同,它会在创建第一个类的对象,或第一次访问类中的静态成员时被调用。 且对于第一种情况,静态构造函数早于构造函数被调用。

		// 在Start中
        Employee employee1 = new Employee();
        Employee employee2 = new Employee();
        // 输出:
        // Static Constructor called
        // Constructor called
        // Constructor called
        // 在Start中
        Debug.Log(Employee.companyName);
        // 输出:
        // Static Constructor called
        // Tencent

正如定义,静态成员适用于那些不依赖于类的实例,只需要一份通用实例的成员。举个例子,用于计数的变量count和打印提示信息的方法print就可以声明为静态成员。现在就来看这样一个例子。

在这个例子中,我们要通过按键动态地生成Enemy,这些Enemy经过3秒就会自动销毁。我们还要设置一个Text的UI组件,显示当前存活的Enemy数量。

首先搭建结构。创建一个敌人的预制体用于动态生成,并绑一个脚本Enemy。创建一个Text,用于展示敌人数量。创建Spawn Manager和UI Manager空物体,并挂载相应的脚本SpawnManager和UIManager,用于控制生成敌人和UI。

在这里插入图片描述

在SpawnManager脚本中,我们规定当按下空格键时,就生成一个Enemy:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class SpawnManager : MonoBehaviour
{
    public GameObject enemyPrefab; // 面板上引用到预制体EnemyPrefab
    public static int activeEnemyCount;

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Instantiate(enemyPrefab);
        }
    }
}

在UIManager中,定义一个UpdateEnemyCount函数:(涉及UI操作注意using UnityEngine.UI)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; // 注意

public class UIManager : MonoBehaviour
{
    public Text enemyCount; // 面板上引用到Enemy Count的Text控件

    public void UpdateEnemyCount()
    {
        enemyCount.text = "Active Enemy: " + SpawnManager.activeEnemyCount;
    }
}

在Enemy脚本中,当被创造时(OnEnable),计数加一,刷新UI,并使其3秒后被销毁;销毁时(OnDisable),计数减一,刷新UI:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Enemy : MonoBehaviour
{
    private UIManager _ui;
    private void OnEnable()
    {
        SpawnManager.activeEnemyCount++;
        _ui = GameObject.Find("UI Manager").GetComponent<UIManager>();
        _ui.UpdateEnemyCount();
        Die();
    }
    private void OnDisable()
    {
        SpawnManager.activeEnemyCount--;
        _ui.UpdateEnemyCount();
    }
    private void Die()
    {
        Destroy(this.gameObject, 3); // 3秒后销毁物体
    }
}

正确设置好所有引用,运行:
在这里插入图片描述
可以看到,我们多次按下空格,生成了多个Enemy,它们过3秒消失。计数器也正确显示了。

在下一节,我们来学习属性(Properties)

  • 3
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值