U
tab 01Basics11 lessons — tap to open
09 / 11 · 12 min
Basics

Swap characters on the floor

your project so far

Assets/

Scenes/

Arena.unity

FloorKnightMageArcherGameManager

Scripts/

GridSpawner.csSimpleMover.csCharacterSwitcher.csSwapCamera.cs

Prefabs/

P_Cube

you already havethis lesson adds

This is the milestone of Tab 01. A flat floor, three characters standing on it, and keys 1 / 2 / 3 to switch which one you control.

animated diagram

Only one character is active at a time; the others stay parked on the floor.

Step 1 — three placeholder characters

  1. 1

    GameObject▸3D Object▸Capsule, name it Knight, Position 0, 1, 0.

  2. 2

    A default capsule is 2 m tall with a centre pivot, so Y = 1 puts its feet exactly on the floor.

  3. 3

    Duplicate it twice (Ctrl/Cmd + D) → Mage at -3, 1, 0 and Archer at 3, 1, 0.

  4. 4

    Give each one a coloured material: green, purple, amber. Now you can tell them apart at a glance.

  5. 5

    Create an empty GameObject called Characters and drag all three inside it.

Step 2 — one movement script for all of them

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 gives an instant -1, 0 or 1. GetAxis smooths it over a few frames — raw feels snappier for this.

  • sqrMagnitude is magnitude without the square root: cheaper, and we only compare it to a threshold.

  • Slerp rotates a fraction of the way each frame, which reads as a smooth turn instead of a snap.

Step 3 — the switcher

The trick is simple: keep a list, enable one, disable the rest. Disabling the SimpleMover (not the whole object) keeps every character visible on the floor.

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

    Create an empty GameObject named GameManager and attach CharacterSwitcher.

  2. 2

    In the Inspector, set the Characters list size to 3 and drag Knight, Mage, Archer into the slots.

  3. 3

    Drag a flattened cylinder (scale 1.2, 0.02, 1.2) into Highlight Ring so you can see who is selected.

  4. 4

    Press Play, move with WASD, switch with 1 2 3 or Tab.

Why disable the script, not the GameObject?

✓ characters[i].enabled = false

The capsule stays on the floor, visible and solid. It simply stops reading input.

✖ SetActive(false)

The whole character vanishes from the scene — wrong for a party standing on a floor.

Step 4 — make the camera follow whoever is active

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);
    }
}

What the arena can do now

  • A 3D scene with a flat floor, materials, a camera and a light.

  • Block prefabs you can stamp out by hand or from a loop.

  • Multiple characters on that floor, with control passing between them.

  • The next lesson puts a menu and music on top of all of this, without touching any of it.

  • Tab 02 upgrades the Knight in place — same GameObject, same name, same slot in this switcher — into a real character with a model, animation, skills and artifacts. Mage and Archer stay capsules so you can see the difference.