TkyStm
TkyStm

Reputation: 71

Passing Monster variables to Battle controller

I'm building a RPG game in Unity and I have some trouble with my battle system. I have a world scene which is populated by various monsters, if the player collides with the monster it loads the battle Scene. I want to pass the name and ID# of the enemy controller so it can load the correct sprites and prefab (the battle scene is generic). The problem is that my monster object (in this case GrassSlug) is in a different scene (world scene) than my battle controller (battle scene). How can I communicate these values to my battle controller? Do I need to add an extra controller which doesn't get destroyed on load? (I current have a GameManager like that and a SkillManager).

GrassSlug.cs (GameObject in world scene)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GrassSlug : Monster {
    private string enemyName = "Grass Slug";
    private int enemyID = 001;
}

Monster.cs (GameObject in world scene)

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

public class Monster : Character {  
    void OnCollisionEnter2D(Collision2D other)
    {
        if (other.collider.tag == "Player") {
            SceneManager.LoadScene("Battle");
        }
    }
}

BattleController.cs (GameObject in Battle scene)

using Random = System.Random;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class BattleController : MonoBehaviour {
    private Stat playerHealth;
    private Stat enemyHealth;
    private static Random random = new Random();
    private int playerDamage;
    private int enemyDamage;
    public Button attackButton;
    public Button escapeButton;
    public Transform victoryText;
    public GameObject canvas;
    public GameObject button;
    public Canvas battleUI;

    void Start () {
        InitHealth();
        InitUI();
    }

    // <summary>
    // Init player and enemy health
    // </summary>
    private void InitHealth()
    {
        playerHealth.Initialize(100, 100);
        enemyHealth.Initialize(100, 100);
    }

    // <summary>
    // Set up main battle UI
    // </summary>
    private void InitUI()
    {
        Button AttackButton = attackButton.GetComponent<Button>();
        AttackButton.onClick.AddListener(PlayerAttack);

        Button EscapeButton = escapeButton.GetComponent<Button>();
        EscapeButton.onClick.AddListener(ReturnScene);
    }

    // <summary>
    // Function for the player attack
    // Calculates player's damage and adds XP to the skills
    // </summary>
    private void PlayerAttack () 
    {
        playerDamage = random.Next(20);
        enemyHealth.CurrentValue -= playerDamage;
        GameController.Instance.attackXP += playerDamage;
        GameController.Instance.hitpointsXP += playerDamage;

        if(enemyHealth.CurrentValue <= 0) {
            Victory();
        } else {
            EnemyAttack();
        }
    }

    // <summary>
    // Function for enemy attack
    // Calculates enemy's damage and adds XP to the  players' skills
    // </summary>
    private void EnemyAttack () {
        enemyDamage = random.Next(10);
        playerHealth.CurrentValue -= enemyDamage;
        GameController.Instance.defenceXP += enemyDamage;
        GameController.Instance.SkillDebug();

        if(playerHealth.CurrentValue <= 0) {
            Debug.Log("You are defeated!");
        }
    }

    // <summary>
    // Change UI when player wins the battle
    // </summary>
    private void Victory() {
        Instantiate(victoryText, new Vector3(0, 1.75f, 0), Quaternion.identity);

        GameObject newCanvas = Instantiate(canvas) as GameObject;
        GameObject newButton = Instantiate(button) as GameObject;
        newButton.transform.SetParent(newCanvas.transform, false);

        Button NewButton = newButton.GetComponent<Button>();
        NewButton.onClick.AddListener(ReturnScene);

        battleUI.gameObject.SetActive(false);
    }

    // <summary>
    // Return to the previous screen
    // Note: Currently only supports going back to the "Hometown" scene
    // </summary>
    private void ReturnScene () {
        SceneManager.LoadScene("Hometown");
    }
}

Upvotes: 1

Views: 133

Answers (2)

Steven Coull
Steven Coull

Reputation: 478

A simple solution is to create a static method and private static fields in your BattleController.

public class BattleController : MonoBehaviour {
    private static string enemyName;
    private static int enemyID;

    public static void SetEnemy(string name, int id)
    {
        enemyName = name;
        enemyID = id;
    }
    //other code
}

Then call the method before loading the scene.

public class Monster : Character {  
    void OnCollisionEnter2D(Collision2D other)
    {
        if (other.collider.tag == "Player") {
            BattleController.SetEnemy(enemyName, enemyID)
            SceneManager.LoadScene("Battle");
        }
    }
}

In your example the monster's name and ID are set as private fields in the GrassSlug class, but for this solution you'd need to add them to the Monster class as protected fields, then set them in GrassSlug.

If you need to share more information with the Battle Controller, you might want to just pass the Monster implementation to the Battle Controller instead of just its name and ID.

Upvotes: 0

Wojtek Pojda
Wojtek Pojda

Reputation: 134

You can either create a new Don't Destroy On Load object that will hold that information for you, or just keep those data in static field. Static fields are not destroyed while changing scenes.

I guess you could also create a ScriptableObject for keeping this data, but this is not the best solution in this case in my opinion.

Upvotes: 1

Related Questions