U
章 01基础11 课 — 点击打开
09 / 11 · 12 分钟
基础

在地面上切换角色

到目前为止的项目

Assets/

Scenes/

Arena.unity

FloorKnightMageArcherGameManager

Scripts/

GridSpawner.csSimpleMover.csCharacterSwitcher.csSwapCamera.cs

Prefabs/

P_Cube

你已经有的这一课新增

这是 Tab 01 的里程碑。一片平地板、三个站在上面的角色,按键 1 / 2 / 3 切换你控制哪一个。

动态图解

同一时刻只有一个角色是激活的,其他人都站在地板上等着。

第 1 步 —— 三个占位角色

  1. 1

    GameObject▸3D Object▸Capsule,命名 Knight,Position 设为 0, 1, 0。

  2. 2

    默认 Capsule 高 2 m,轴心在中心,所以 Y = 1 时脚刚好落在地板上。

  3. 3

    复制两次(Ctrl/Cmd + D)→ Mage 放 -3, 1, 0,Archer 放 3, 1, 0。

  4. 4

    给每个角色一个彩色 material:绿、紫、琥珀色。一眼就分得清谁是谁。

  5. 5

    新建一个叫 Characters 的空 GameObject,把三个都拖进去。

第 2 步 —— 一个移动脚本大家共用

SimpleMover.cs — attach to all three characters
using UnityEngine;

public class SimpleMover : MonoBehaviour
{
    [SerializeField] private float speed = 6f;
    [SerializeField] private float turnSpeed = 12f;

    void Update()
    {
        // -1 .. 1 from A/D and W/S
        float h = Input.GetAxisRaw("Horizontal");
        float v = Input.GetAxisRaw("Vertical");

        Vector3 dir = new Vector3(h, 0f, v);
        if (dir.sqrMagnitude < 0.01f) return;      // no input, nothing to do

        dir.Normalize();                            // diagonal is not faster
        transform.position += dir * speed * Time.deltaTime;

        // face the direction of travel
        Quaternion target = Quaternion.LookRotation(dir);
        transform.rotation = Quaternion.Slerp(transform.rotation, target, turnSpeed * Time.deltaTime);
    }
}
  • GetAxisRaw 直接给你 -1、0 或 1。GetAxis 会在几帧之间做平滑 —— 这里用 raw 手感更干脆。

  • sqrMagnitude 是不开方根的长度:更省,而且我们只是拿它跟一个阈值比大小。

  • Slerp 每帧只转过一小段角度,所以看起来是平滑地转身,而不是一下扭过去。

第 3 步 —— 切换器

技巧很简单:维护一个列表,启用一个,其余禁用。禁用的是 SimpleMover(不是整个对象),所以每个角色都还站在地板上看得见。

CharacterSwitcher.cs — attach to an empty GameManager
using System.Collections.Generic;
using UnityEngine;

public class CharacterSwitcher : MonoBehaviour
{
    [SerializeField] private List<SimpleMover> characters = new List<SimpleMover>();
    [SerializeField] private Transform highlightRing;   // optional marker

    private int activeIndex = 0;

    void Start()
    {
        Select(0);
    }

    void Update()
    {
        // number keys 1..9
        for (int i = 0; i < characters.Count && i < 9; i++)
            if (Input.GetKeyDown(KeyCode.Alpha1 + i))
                Select(i);

        // Tab cycles to the next one
        if (Input.GetKeyDown(KeyCode.Tab))
            Select((activeIndex + 1) % characters.Count);
    }

    public void Select(int index)
    {
        if (index < 0 || index >= characters.Count) return;

        activeIndex = index;

        for (int i = 0; i < characters.Count; i++)
            characters[i].enabled = (i == index);      // only one may move

        if (highlightRing != null)
            highlightRing.SetParent(characters[index].transform, false);

        Debug.Log("Now controlling: " + characters[index].name);
    }

    public Transform ActiveCharacter => characters[activeIndex].transform;
}
  1. 1

    新建一个空 GameObject 叫 GameManager,挂上 CharacterSwitcher。

  2. 2

    在 Inspector 里把 Characters 列表长度设为 3,再把 Knight、Mage、Archer 拖进各个槽位。

  3. 3

    把一个压扁的 cylinder(scale 1.2, 0.02, 1.2)拖进 Highlight Ring,就能看出当前选中的是谁。

  4. 4

    点 Play,用 WASD 移动,用 1 2 3 或 Tab 切换。

为什么禁用的是脚本,而不是 GameObject?

✓ characters[i].enabled = false

capsule 还站在地板上,看得见、也撞得到。它只是不再读取输入而已。

✖ SetActive(false)

整个角色会从场景里消失 —— 而你要的是大家都站在地板上。

第 4 步 —— 让相机跟着当前激活的角色

SwapCamera.cs — attach to Main Camera
using UnityEngine;

public class SwapCamera : MonoBehaviour
{
    [SerializeField] private CharacterSwitcher switcher;
    [SerializeField] private Vector3 offset = new Vector3(0f, 12f, -14f);
    [SerializeField] private float smooth = 4f;

    void LateUpdate()                      // after everyone has moved
    {
        Transform target = switcher.ActiveCharacter;
        Vector3 wanted = target.position + offset;

        transform.position = Vector3.Lerp(transform.position, wanted, smooth * Time.deltaTime);
        transform.LookAt(target.position + Vector3.up);
    }
}

现在这个场地能做到什么

  • 一个 3D 场景,有平地板、材质、相机和灯光。

  • 方块 prefab,能手摆也能用循环刷出来。

  • 同一块地板上的多个角色,控制权在他们之间来回传递。

  • 下一课在这些之上再加菜单和音乐,而不改动里面的任何东西。

  • Tab 02 会就地升级 Knight —— 还是同一个 GameObject、同一个名字、在 switcher 里还是同一个槽位 —— 把它变成有模型、动画、技能和 artifact 的真正角色。Mage 和 Archer 继续当 capsule,好让你看出差别。