DEVLOG 8 – MONDAY 3RD APRIL

After my break, I’m ready to continue working on my project. I mentioned previously that I’d work on redesigning my level layouts, which I feel I have done successfully. I’ve looked into the what makes a compelling level layout, as well as revisiting what makes a good Metroidvania, namely rewarding exploration, utility-gated (i.e. abilities) progression and guided non-linearity (i.e. guiding player’s through a non-linear path). Guided non-linearity is a bit difficult to achieve given it’s just me working on the project, however, I did create a map which I think offers a couple routes of exploration, both of which offer meaningful rewards to the player. You can see this route below:

A good majority of this week I’ve also been working on trying to get player respawn to work. They’re currently able to respawn to a point that is in the same room (or scene) but unable to respawn if their last respawn point is in another scene. I think this is the big issue, as the script I’ve made is able to detect how many respawn points are in the current scene, however it’s unable to find other respawn spots through the many scenes I have.

Current PlayerHealth Script with Same-Room Shrine Functionality:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
using System.Linq;

public class PlayerHealth : MonoBehaviour
{
    public int startingLives = 5; // The number of lives the player starts with
    public int maxLives;
    public int currentLives; // The number of lives the player starts with
    public Transform respawnPoint;

    GameObject nearestSpawnPoint = null;

    // Set the player's initial health
    void Start()
    {
        currentLives = startingLives;
        maxLives = startingLives;
    }

    // Take damage and update the health display
    public void TakeDamage(int amount)
    {
        currentLives -= amount;

        // Check if the player has run out of lives
        //if (currentLives <= 0)
        //{
            //Die();
        //}
    }

    public void UpgradeHealth()
    {
        maxLives += 1;
        currentLives = maxLives;
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("Enemy"))
        {
            TakeDamage(1);
        }

        if (collision.gameObject.CompareTag("Branch"))
        {
            Debug.Log("Branch hit");
            TakeDamage(1);
            // Check if the player has run out of lives
            if (currentLives <= 0)
            {
                Die();
            }
            else
            {
                FindSpawnPoint();
            }
        }

        if (collision.gameObject.CompareTag("HealthUpgrade"))
        {
            GameObject HealthUpgrade = GameObject.FindWithTag("HealthUpgrade");
            Debug.Log("Upgrade Health");
            UpgradeHealth();
            Destroy(HealthUpgrade);
        }
    }

    // Method to handle the player's death
    void Die()
    {
        // Reset the player's health
        currentLives = startingLives;
        RespawnAtNearestDeathSpawnPoint();
    }

    void FindSpawnPoint()
    {
        // Find the nearest spawn point to the player's current position
        GameObject[] spawnPoints = GameObject.FindGameObjectsWithTag("SpawnPoint");
        //GameObject nearestSpawnPoint = null;
        float minDistance = float.MaxValue;
        foreach (GameObject spawnPoint in spawnPoints)
        {
            float distance = Vector3.Distance(transform.position, spawnPoint.transform.position);
            if (distance < minDistance)
            {
                nearestSpawnPoint = spawnPoint;
                minDistance = distance;
            }
        }

        // Move the player to the nearest spawn point
        transform.position = nearestSpawnPoint.transform.position;
    }

    // Find the nearest last visited death spawn point to the player's current position
    DeathSpawnPoint FindDeathSpawnPoint()
    {
        //DeathSpawnPoint[] deathSpawnPoints = FindObjectsOfType<DeathSpawnPoint>();
        //Debug.Log("Found " + deathSpawnPoints.Length + " death spawn points.");

        //DeathSpawnPoint nearestDeathSpawnPoint = null;
        //float minDistance = float.MaxValue;

        //foreach (DeathSpawnPoint deathSpawnPoint in deathSpawnPoints)
        //{
            //if (deathSpawnPoint.HasVisited())
            //{
                //float distance = Vector3.Distance(transform.position, deathSpawnPoint.transform.position);
                //if (distance < minDistance)
                //{
                    //nearestDeathSpawnPoint = deathSpawnPoint;
                    //minDistance = distance;
                //}
            //}
        //}

        //return nearestDeathSpawnPoint;

        DeathSpawnPoint[] deathSpawnPoints = FindObjectsOfType<DeathSpawnPoint>();
        Debug.Log("Found " + deathSpawnPoints.Length + " death spawn points.");

        DeathSpawnPoint nearestDeathSpawnPoint = null;
        float minDistance = float.MaxValue;

        foreach (DeathSpawnPoint deathSpawnPoint in deathSpawnPoints)
        {
            if (deathSpawnPoint.HasVisited())
            {
                float distance = Vector3.Distance(transform.position, deathSpawnPoint.transform.position);
                if (distance < minDistance)
                {
                    nearestDeathSpawnPoint = deathSpawnPoint;
                    minDistance = distance;
                }
            }
        }

        if (nearestDeathSpawnPoint != null)
        {
            return nearestDeathSpawnPoint;
        }
        else
        {
            // No death spawn point found in current scene; search other scenes
            for (int i = 0; i < SceneManager.sceneCount; i++)
            {
                Scene scene = SceneManager.GetSceneAt(i);
                if (scene != gameObject.scene && scene.isLoaded)
                {
                    SceneManager.SetActiveScene(scene);
                    deathSpawnPoints = scene.GetRootGameObjects().SelectMany(g => g.GetComponentsInChildren<DeathSpawnPoint>()).ToArray();
                    Debug.Log("Found " + deathSpawnPoints.Length + " death spawn points in scene " + scene.name);
                    foreach (DeathSpawnPoint deathSpawnPoint in deathSpawnPoints)
                    {
                        if (deathSpawnPoint.HasVisited())
                        {
                            float distance = Vector3.Distance(transform.position, deathSpawnPoint.transform.position);
                            if (distance < minDistance)
                            {
                                nearestDeathSpawnPoint = deathSpawnPoint;
                                minDistance = distance;
                            }
                        }
                    }
                }
            }

            if (nearestDeathSpawnPoint != null)
            {
                SceneManager.LoadScene(nearestDeathSpawnPoint.gameObject.scene.name);
                transform.position = nearestDeathSpawnPoint.transform.position;
                nearestDeathSpawnPoint.SetVisited(false);
                return nearestDeathSpawnPoint;
            }
            return nearestDeathSpawnPoint;
        }
    }

    void RespawnAtNearestDeathSpawnPoint()
    {
        DeathSpawnPoint nearestDeathSpawnPoint = FindDeathSpawnPoint();

        if (nearestDeathSpawnPoint != null)
        {
            // Get the name of the scene that the nearest death spawn point is in
            string sceneName = nearestDeathSpawnPoint.gameObject.scene.name;

            // Activate the scene that the nearest death spawn point is in
            Scene targetScene = SceneManager.GetSceneByName(sceneName);
            SceneManager.SetActiveScene(targetScene);

            // Load the scene
            //SceneManager.LoadScene(sceneName);
            transform.position = nearestDeathSpawnPoint.transform.position;
            nearestDeathSpawnPoint.SetVisited(false);
        }
        else
        {
            // No death spawn point found; respawn at the nearest spawn point
            FindSpawnPoint();
        }
    }
}

It’s unfortunate that I’ve worked on this for the past couple days, with no visible progress in sight. I have sent a message to Maddi, but I’m aware that she has work she herself needs to complete, and was reluctant to send that message at first, but felt it was necessary if I’m to solve this issue. I’ll be trying again next week, but I’m not so sure I’ll be able to find a working solution.

Leave a Comment

Your email address will not be published. Required fields are marked *