【问题标题】:Passing Monster variables to Battle controller将怪物变量传递给战斗控制器
【发布时间】:2019-01-30 13:12:18
【问题描述】:

我正在 Unity 中构建一个 RPG 游戏,但我的战斗系统有些问题。我有一个由各种怪物组成的世界场景,如果玩家与怪物发生碰撞,它会加载战斗场景。我想传递敌人控制器的名称和 ID#,以便它可以加载正确的精灵和预制件(战斗场景是通用的)。问题是我的怪物对象(在本例中为 GrassSlug)与我的战斗控制器(战斗场景)位于不同的场景(世界场景)中。如何将这些值传达给我的战斗控制器?我是否需要添加一个不会在加载时被破坏的额外控制器? (我目前有一个这样的 GameManager 和一个 SkillManager)。

GrassSlug.cs(世界场景中的游戏对象)

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

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

Monster.cs(世界场景中的游戏对象)

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(战斗场景中的游戏对象)

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

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    您可以创建一个新的Don't Destroy On Load 对象来为您保存该信息,或者将这些数据保存在静态字段中。改变场景时静态场不会被破坏。

    我想你也可以创建一个 ScriptableObject 来保存这些数据,但在我看来这不是这种情况下的最佳解决方案。

    【讨论】:

      【解决方案2】:

      一个简单的解决方案是在你的 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
      }
      

      然后在加载场景之前调用该方法。

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

      在您的示例中,怪物的名称和 ID 在 GrassSlug 类中设置为私有字段,但对于此解决方案,您需要将它们作为受保护字段添加到 Monster 类中,然后在 GrassSlug 中设置它们。

      如果您需要与战斗控制器共享更多信息,您可能只想将 Monster 实现传递给战斗控制器,而不仅仅是其名称和 ID。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-06
        相关资源
        最近更新 更多