Menu
CoddyTech

小型组件

本课属于 Coddy Unity 学习旅程的“Unity 游戏架构”单元。第 1 课,共 64 课。

GameObject 是一个组件列表,你编写的每个脚本都是其中的一个组件。Unity 游戏通过让每个脚本负责一项工作,并将多个脚本放到一个对象上来构建。玩家的移动、射击和生命值都可以放在同一个 PlayerController 中,但如果将它们作为三个组件:Mover、Shooter 和 Health,每个组件也可以放到其他对象上:

public class Health : MonoBehaviour
{
    public int hp = 3;

    public void TakeDamage(int amount)
    {
        hp -= amount;
        if (hp <= 0)
        {
            Destroy(gameObject);
        }
    }
}
  • 玩家:Mover、Shooter、Health
  • 炮台:Shooter、Health
  • 箱子:Health

如果使用普通的 C# 类,你可能会构建一棵继承树:Character,然后是 ShootingCharacter : Character,再然后是 Player : ShootingCharacter。炮台会射击,但不会行走;箱子只会破碎,所以每增加一种新对象,就意味着要调整这棵树。使用组件时,新对象就是将已有脚本组合成新的搭配,然后在 Inspector 中放到一起,并且每个脚本都可以在那里设置自己的值:一个对象上的 Mover 速度较慢,另一个对象上的速度较快。

同一对象上的组件共享它的 Transform,因此每个组件都应该只修改自己负责的部分。使用 transform.position += 增加 x 和 z 的 Mover 不会改动 y,因此同一对象上的 Jumper 仍然可以改变高度。如果 Mover 把整个位置设为 new Vector3(x, 0.5f, z),就会每帧把 y 重置,从而抵消跳跃效果。

challenge icon

挑战

简单

拆分 Boat.cs,让每个脚本只负责一项工作。

  1. 把上下浮动的逻辑移到 Bobber 中:在 Start() 中设置 startY,在 Update() 中实现上下浮动,并使用自己的 height 和 speed。
  2. 把闪烁的逻辑移到 Blinker 中,并使用它自己的计时器。
  3. 从 Boat 中删除这两项工作及其字段,让它只负责转向。

按下 “开始”:鸭子会上下浮动,浮标会闪烁,小船会转向。然后点击 “检查”。

亲手试试

using UnityEngine;
using UnityEngine.InputSystem;

// 一个脚本,完成三件事:控制方向、上下浮动和闪烁。
public class Boat : MonoBehaviour
{
    public float speed = 3f;
    public float bobHeight = 0.1f;
    public float bobSpeed = 2f;
    public Renderer lamp;
    public float blinkInterval = 0.5f;

    private InputAction moveAction;
    private float startY;
    private float blinkTimer;

    void Start()
    {
        moveAction = InputSystem.actions.FindAction("Move");
        startY = transform.position.y;
    }

    void Update()
    {
        // 控制方向
        Vector2 input = moveAction.ReadValue<Vector2>();
        transform.position += new Vector3(input.x, 0f, input.y) * speed * Time.deltaTime;

        // 上下浮动
        Vector3 p = transform.position;
        p.y = startY + Mathf.Sin(Time.time * bobSpeed) * bobHeight;
        transform.position = p;

        // 闪烁
        blinkTimer += Time.deltaTime;
        if (blinkTimer >= blinkInterval)
        {
            blinkTimer -= blinkInterval;
            lamp.enabled = !lamp.enabled;
        }
    }
}

Unity 游戏架构中的所有课

自己练习: Unity 在线编辑器