Day 11 - Keeping an Eye on the NPCs

Finding something interesting to look at, part 1…


“Ok, we’re watching”

I keep going completely off the rails with this camera controller, unable to navigate back to seeing any of the map, let alone something interesting. Let’s do something about that:

Managers/GUIManager.csGitLab
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
void Update () {
    if (Input.GetKeyDown (KeyCode.Z)) {
        map_manager.CycleZ(false);
    }
    if (Input.GetKeyDown (KeyCode.A)) {
        map_manager.CycleZ(true);
    }
    if (Input.GetKeyDown (KeyCode.Space)) {
        mainCamera.ReturnToHome();
    }
    if (Input.GetKeyDown (KeyCode.N)) {
        Vector3 randomNpcCoords = map_manager.locateRandomNpc();
        mainCamera.lookAtNpc(randomNpcCoords);
    }
}

So now Space will return the camera to its original position, and N will make us look at a random NPC? To do that, we’ll need to save (and be able to restore) the initial camera settings:

CameraControlScript.csGitLab
14
15
16
17
18
19
20
21
22
23
24
Vector3 originalPosition; Quaternion originalRotation;

void Start() {
    originalPosition = transform.position;
    originalRotation = transform.rotation;
}
 
public void ReturnToHome() {
    transform.position = originalPosition;
    transform.rotation = originalRotation;
}

And have a way to look at a particular map cell:

CameraControlScript.csGitLab
95
96
97
98
public void lookAtNpc(Vector3 npcCoords) {
    transform.position = new Vector3((-1f) * npcCoords.x, (-1f) * npcCoords.y, (0.1f * npcCoords.z) + 15f);
    transform.LookAt(new Vector3((-1f) * npcCoords.x, (-1f) * npcCoords.y, npcCoords.z));
}

So now we can move the camera to 15 units above a cell, looking down. How do we grab a random NPC at which to look?

Managers/MapManager.csGitLab
310
311
312
313
314
315
316
System.Random myRandom = new System.Random();

public Vector3 locateRandomNpc() {
    if (cellsContainingNpcs.Count == 0) return Vector3.zero;
    List<Vector3> cells = new List<Vector3>(cellsContainingNpcs.Keys);
    return cells[myRandom.Next(cells.Count)];
}

We need a System.Random because we want integers, and UnityEngine.Random will only give us floats.

Demonstration

Hitting Space: Hitting N: Yes, I added in a few more of the common surface NPC types. But sometimes we’re not seeing the NPC that we’re centered on; what’s up with that?

Oops

If we switch to an NPC that’s underground, we don’t see it unless we’ve manually disappeared the map layers above it. That won’t do. We need to be more dynamic in updating the Z-layer filter. We’ll split it out into a method we can call with an arbitrary Z, and keep track of that as well:

Managers/MapManager.csGitLab
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
public void UpdateZ(float z) {
    Renderer currBlockRend;
    foreach (Vector3 v in cell_transforms.Keys) {
        currBlockRend = cell_transforms[v].GetComponent<Renderer>();
        if (v.z > z) {
            currBlockRend.enabled = false;
        } else {
            currBlockRend.enabled = true;
        }
    }
    zTop = z;
}

public void CycleZ(bool up) {
    currentZTopIdx += (up ? 1 : -1);
    if (currentZTopIdx < 0) currentZTopIdx = 0;
    if (currentZTopIdx >= zPlanes.Length) currentZTopIdx = zPlanes.Length - 1;
    UpdateZ(zPlanes[currentZTopIdx]);
}

We’ll call that method directly when we look at a new NPC, and display the actual top Z variable:

Managers/GUIManager.csGitLab
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
    if (Input.GetKeyDown (KeyCode.N)) {
        Vector3 randomNpcCoords = map_manager.locateRandomNpc();
        mainCamera.lookAtNpc(randomNpcCoords);
        map_manager.UpdateZ(randomNpcCoords.z + 1f);
    }
}
        
void OnGUI(){
    GUI.Box (new Rect (0,0,100,50), "# of cells\n" + map_manager.num_cells);
    GUI.Box (new Rect (Screen.width - 100,0,100,50), "# of blocks\n" + map_manager.num_blocks);
    GUI.Box (new Rect (0,Screen.height - 50,100,50), "Z top\n" + map_manager.zTop);
    StringBuilder builder = new StringBuilder();
    foreach (int gameRound in map_manager.activeGameRounds)
        builder.Append(gameRound).Append(" ");
    GUI.Box (new Rect (Screen.width - 100,Screen.height - 50,100,50), "Game Round\n" + builder.ToString());
}

Better?

Yep. And yet: Something to fix tomorrow.


Day 11 code - client