Skip to content

unity-script-system

基础概念 ​

Unity 的脚本系统,你可以先理解成:

脚本就是你写的 C# 组件,用来控制 GameObject 的行为。

Unity 里不是“写一个 main 函数,然后程序从 main 开始跑”。 Unity 的逻辑是:你把脚本挂到某个 GameObject 上,Unity 在合适的时机自动调用脚本里的函数。

1. 脚本本质上也是 Component ​

比如你写一个脚本:

c
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    void Update()
    {
        Debug.Log("玩家正在运行逻辑");
    }
}

这个 PlayerController 继承了 MonoBehaviour,所以它就可以挂到 GameObject 上。

挂上去后,它就变成这样:

c
Player
├─ Transform
├─ SpriteRenderer
├─ Rigidbody2D
├─ Collider2D
└─ PlayerController

也就是说: 脚本不是独立运行的代码文件,而是一个挂在对象身上的行为组件。

2. MonoBehaviour 是 Unity 脚本的核心基类 ​

大多数 Unity 脚本都会这样写:

c
public class MyScript : MonoBehaviour
{
}

MonoBehaviour 给了你很多 Unity 特有能力,比如:

  • 可以挂到 GameObject 上
  • 可以使用 Start()
  • 可以使用 Update()
  • 可以访问 transform
  • 可以使用 GetComponent
  • 可以启用/禁用脚本
  • 可以接收碰撞、触发、鼠标、生命周期事件

如果一个类没有继承 MonoBehaviour,它通常就不能直接挂到 GameObject 上。

3. 脚本生命周期:Unity 自动调用这些函数 ​

这是脚本系统最重要的部分。

常用生命周期顺序大概是:

c
Awake()
↓
OnEnable()
↓
Start()
↓
Update()
↓
LateUpdate()
↓
OnDisable()
↓
OnDestroy()

再加一个物理专用的:

c
FixedUpdate()

你可以这样理解:

函数什么时候执行常见用途
Awake()对象加载时最早执行初始化内部变量、获取组件
OnEnable()脚本/对象启用时执行监听事件、重置状态
Start()第一次 Update 前执行一次依赖其他对象初始化后的逻辑
Update()每帧执行一次输入、普通逻辑、计时
FixedUpdate()固定时间间隔执行物理移动、Rigidbody 操作
LateUpdate()Update 后执行摄像机跟随、收尾逻辑
OnDisable()脚本/对象禁用时执行取消监听、暂停逻辑
OnDestroy()对象销毁时执行清理资源

最常见的新手组合是:

c
void Awake()
{
    // 获取组件
}

void Start()
{
    // 初始化游戏开始状态
}

void Update()
{
    // 每帧检查输入
}

void FixedUpdate()
{
    // 处理物理移动
}

4. Update 和 FixedUpdate 的区别 ​

这个特别重要。

Update() 是每一帧执行一次。 如果电脑性能高,一秒可能执行 120 次;性能低,可能一秒执行 30 次。

适合放:

  • 键盘输入
  • 鼠标输入
  • UI 检查
  • 普通逻辑
  • 动画状态判断
  • 倒计时

例如:

c
void Update()
{
    if (Input.GetKeyDown(KeyCode.Space))
    {
        Debug.Log("按下空格");
    }
}

FixedUpdate() 是固定时间执行,默认大约每秒 50 次。 适合放物理相关逻辑。

比如:

c
void FixedUpdate()
{
    rb.linearVelocity = new Vector2(moveX * speed, rb.linearVelocity.y);
}

简单记:

输入放 Update,物理放 FixedUpdate。

5. transform 是最常用的内置引用 ​

只要脚本挂在某个 GameObject 上,你就可以直接用:

c
transform

它代表当前对象的 Transform 组件。

例如:

c
void Update()
{
    transform.position += new Vector3(1, 0, 0) * Time.deltaTime;
}

这表示:当前对象每秒往右移动一点。

注意这里用了:

c
Time.deltaTime

它表示上一帧到这一帧经过了多少秒。 移动、计时、平滑变化时经常要用它,否则不同帧率下速度会不一样。

6. Inspector 参数:让脚本变得可调 ​

比如:

c
public float speed = 5f;

这个字段会出现在 Inspector 面板里。

更推荐这样写:

c
[SerializeField] private float speed = 5f;

意思是: 代码里保持 private,但 Unity Inspector 里仍然能调。

完整例子:

c
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    [SerializeField] private float speed = 5f;

    void Update()
    {
        float x = Input.GetAxisRaw("Horizontal");
        transform.position += new Vector3(x, 0, 0) * speed * Time.deltaTime;
    }
}

这样你不用改代码,就可以在 Unity 里调整玩家速度。

7. 脚本怎么访问组件 ​

假设 Player 身上有 Rigidbody2D,脚本也挂在 Player 上。

c
Player
├─ Rigidbody2D
└─ PlayerController

脚本里可以这样拿到它:

c
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    private Rigidbody2D rb;

    void Awake()
    {
        rb = GetComponent<Rigidbody2D>();
    }
}

核心是:

c
GetComponent<Rigidbody2D>();

意思是: 从当前 GameObject 身上找到 Rigidbody2D 组件。

常用方式:

c
GetComponent<T>()              // 找自己身上的组件
GetComponentInChildren<T>()    // 找子对象里的组件
GetComponentInParent<T>()      // 找父对象里的组件

新手更推荐 Inspector 拖拽引用:

c
[SerializeField] private Rigidbody2D rb;

然后在 Inspector 里把对象拖进去。

8. 一个完整的玩家移动脚本 ​

2D 示例:

c
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    [SerializeField] private float speed = 5f;

    private Rigidbody2D rb;
    private float moveX;

    void Awake()
    {
        rb = GetComponent<Rigidbody2D>();
    }

    void Update()
    {
        moveX = Input.GetAxisRaw("Horizontal");
    }

    void FixedUpdate()
    {
        rb.linearVelocity = new Vector2(moveX * speed, rb.linearVelocity.y);
    }
}

这里发生了什么:

c
Awake       获取 Rigidbody2D
Update      读取键盘输入
FixedUpdate 控制物理速度

这就是比较标准的脚本分工。

9. 碰撞和触发事件 ​

如果对象身上有 Collider,Unity 可以自动调用碰撞函数。

3D 常用:

c
void OnCollisionEnter(Collision collision)
{
    Debug.Log("撞到了:" + collision.gameObject.name);
}

2D 常用:

c
void OnCollisionEnter2D(Collision2D collision)
{
    Debug.Log("撞到了:" + collision.gameObject.name);
}

如果 Collider 勾选了 Is Trigger,用触发函数:

c
void OnTriggerEnter2D(Collider2D other)
{
    Debug.Log("进入触发区:" + other.gameObject.name);
}

简单区别:

类型是否会挡住物体常见用途
Collision会真实碰撞地面、墙、箱子
Trigger不阻挡,只检测进入金币、传送门、检测区

10. 实例化和销毁对象 ​

脚本可以动态创建对象,比如生成子弹、敌人、特效。

c
[SerializeField] private GameObject bulletPrefab;
[SerializeField] private Transform firePoint;

void Shoot()
{
    Instantiate(bulletPrefab, firePoint.position, firePoint.rotation);
}

销毁对象:

c
Destroy(gameObject);

其中:

c
gameObject

代表当前脚本挂着的那个 GameObject。

11. 协程 Coroutine:延迟和分步骤执行 ​

如果你想“等 2 秒后再做某事”,可以用协程。

c
using System.Collections;
using UnityEngine;

public class Example : MonoBehaviour
{
    void Start()
    {
        StartCoroutine(WaitAndPrint());
    }

    IEnumerator WaitAndPrint()
    {
        Debug.Log("开始等待");
        yield return new WaitForSeconds(2f);
        Debug.Log("2 秒后执行");
    }
}

协程常用于:

  • 延迟执行
  • 技能冷却
  • 波次刷怪
  • 渐隐渐现
  • 分阶段动画逻辑

12. 脚本之间怎么通信 ​

常见方式有三种:

第一种:直接拖引用。

c
[SerializeField] private Health health;

void Attack()
{
    health.TakeDamage(10);
}

第二种:GetComponent。

c
Health health = GetComponent<Health>();
health.TakeDamage(10);

第三种:事件系统。

适合稍微进阶后学习,比如玩家死亡通知 UI、音效、任务系统。

新手阶段先掌握前两种就够了。

13. 常见脚本分类 ​

做游戏时,脚本通常会分成几类:

脚本类型例子负责什么
控制脚本PlayerController玩家输入、移动、跳跃
状态脚本Health血量、死亡
生成脚本EnemySpawner刷怪、生成道具
管理脚本GameManager游戏流程、胜负
UI 脚本UIManager血条、分数、按钮
数据脚本ItemData道具、技能、配置
摄像机脚本CameraFollow跟随玩家

一个好习惯是: 一个脚本只负责一类清晰的事情。

14. 新手最容易犯的错误 ​

第一,脚本文件名和类名不一致。

文件叫:

c
PlayerController.cs

类名也应该是:

c
public class PlayerController : MonoBehaviour

第二,脚本没有挂到 GameObject 上。 只写了代码,但没有拖到对象上,Unity 不会执行。

第三,把物理移动写在 Update 里。 物理对象建议用 Rigidbody,并在 FixedUpdate 中处理。

第四,到处使用 Find()。 GameObject.Find() 能用,但频繁使用会乱、慢、难维护。

第五,一个脚本写太多功能。 比如 PlayerController 里同时写移动、血量、背包、UI、存档,后面会很难改。

15. 建议你的学习顺序 ​

你可以按这个路线练:

  1. 写一个脚本,让 Cube 每秒向右移动。
  2. 用 [SerializeField] 把速度显示到 Inspector。
  3. 用键盘控制 Cube 左右移动。
  4. 用 GetComponent 获取 Rigidbody2D。
  5. 用 FixedUpdate 控制物理移动。
  6. 写碰撞检测,碰到金币后销毁金币。
  7. 用 Instantiate 生成子弹。
  8. 用 Destroy 销毁子弹。
  9. 写一个 Health 脚本控制血量。
  10. 写一个 GameManager 管理胜利和失败。

你可以把 Unity 脚本系统记成这句话:

脚本系统 = MonoBehaviour 生命周期 + Inspector 参数 + 组件访问 + 输入/物理/碰撞/生成逻辑。

掌握这几个,你就能开始真正控制游戏世界了。

参考链接 ​

脚本系统

文章评价

读完这篇,留下你的看法

暂无审核通过的评价。

登录账号后才能评价。

本站访客数0总站访问量0本页访问量0