简体   繁体   English

在 Unity 中使用脚本对象的项目/能力系统

[英]Item/Ability system using scriptableobjects in Unity

I'm new to Unity and I'm having some trouble creating scriptable objects for items to pick up and use in my project.我是 Unity 的新手,在为项目创建可脚本化对象以在我的项目中选取和使用时遇到了一些问题。 I've created the initial set-up to make the items with variables that I can plug-and-play with.我已经创建了初始设置,使项目具有可以即插即用的变量。

What I'm trying to do is:我想要做的是:

1 - plug in a monobehavior script for each new item's behavior when used. 1 - 在使用时为每个新项目的行为插入一个单一行为脚本。

2 - Allow the player to pick up the item on collision and use the item on key command. 2 - 允许玩家在碰撞时拿起物品并使用键盘命令中的物品。 The player should only carry one item at a time.玩家一次只能携带一件物品。

Here is what I have so far.这是我到目前为止所拥有的。

the scriptable object (itemObject.cs)可编写脚本的对象 (itemObject.cs)

[CreateAssetMenu(fileName = "New Item", menuName = "Item")]
public abstract class Item : ScriptableObject {
                public new string name;
                public string description;
                public int damageAmount;
                public int affectDelay;
                public int affectDuration;
                public int affectRange;
                public float dropChance;
                public float itemLife;
}

I have a script that will trigger if the player collides with the object (itemDisplay.cs) Currently, this doesn't do anything but destroys the item.我有一个脚本,如果玩家与对象(itemDisplay.cs)发生碰撞,它将触发当前,这不会做任何事情,只会破坏项目。

public class itemDisplay : MonoBehaviour {

public Item item;

public static bool isActive = false;

void OnTriggerEnter(Collider other)
{

    if (other.gameObject.tag == "Player")
    {

        var playerPickUp = other.gameObject;

        var playerScript = playerPickUp.GetComponent<Player>();
        var playerItem = playerScript.playerItem;

        playerScript.pickUpItem();

        bool isActive = true;

        Object.Destroy(gameObject);

    }
}


void Start () {

}


void Update(){
}

} }

Currently, I have a pickup function and a use item function that's being handled by my player script(Player.cs).目前,我有一个拾取功能和一个由我的播放器脚本(Player.cs)处理的使用项目功能。 Currently, this just toggles a boolean saying that it did something when the item is collided with.目前,这只是切换一个布尔值,说它在项目碰撞时做了一些事情。 My big question is how/where should I create and reference the item ability and how do I pass it to the player script here?我的大问题是我应该如何/在哪里创建和引用项目能力,以及如何将其传递给此处的玩家脚本?

public void pickUpItem()
{
    playerItem = true;
    //itemInHand = itemInHand;
    Debug.Log("You Picked Up An Item!");

   // Debug.Log(playerItem);
    if(playerItem == true){
        Debug.Log("This is an item in your hands!");
    }

}

public void useItem()
{
    //use item and set
    //playerItem to false
    playerItem = false;


}

If your question is "how do I create an instance of an Item in my project", you do that by right clicking in your Project view, then selecting Create -> Item .如果您的问题是“我如何在我的Item中创建Item的实例”,您可以通过右键单击 Project 视图,然后选择Create -> Item Then drag the Item asset that you created from your Project view into the ItemDisplay scene object's item field in the Inspector.然后将您从 Project 视图中创建的Item资产拖到 Inspector 中ItemDisplay场景对象的item字段中。

Regarding how to pick up the item, you would pass the item to your Player script from your ItemDisplay script.关于如何拾取物品,您可以将物品从ItemDisplay脚本传递给您的Player脚本。 You've got most of that already wired up.您已经完成了大部分工作。

public class ItemDisplay : MonoBehaviour
{
   void OnTriggerEnter(Collider other)
   {
      if (other.gameObject.tag == "Player")
      {
         var playerPickUp = other.gameObject;

         var playerScript = playerPickUp.GetComponent<Player>();
         var playerItem = playerScript.playerItem;

         // This is where you would pass the item to the Player script
         playerScript.pickUpItem(this.item);

         bool isActive = true;

         Object.Destroy(gameObject);
      }
   }
}

Then in your Player script...然后在您的Player脚本中...

public class Player : MonoBehaviour
{
   public void PickUpItem(Item item)
   {
      this.playerItem = true;
      this.itemInHand = item;
      Debug.Log(string.Format("You picked up a {0}.", item.name));
   }

   public void UseItem()
   {
      if (this.itemInHand != null)
      {
         Debug.Log(string.Format("You used a {0}.", this.itemInHand.name));
      }
   }
}

You should also make your Item class non-abstract, or leave it abstract and create the appropriate non-abstract derived classes ( Weapon , Potion , etc.).您还应该使您的Item类非抽象,或者让它保持抽象并创建适当的非抽象派生类( WeaponPotion等)。 I put an example of that below.我在下面举了一个例子。

You can't attach a MonoBehaviour to a ScriptableObject if that's what you're trying to do.如果这就是你想要做的,你不能将MonoBehaviour附加到ScriptableObject A ScriptableObject is basically just a data/method container that isn't tied to a scene. ScriptableObject基本上只是一个与场景无关的数据/方法容器。 A MonoBehaviour has to live on an object within a scene. MonoBehaviour必须存在于场景中的对象上。 What you could do however, is add a "use" method to your Item class, and call that from a MonoBehaviour within the scene when the player uses an item.但是,您可以做的是向Item类添加一个“使用”方法,并在玩家使用项目时从场景中的MonoBehaviour调用该方法。

public abstract class Item : ScriptableObject
{
   // Properties that are common for all types of items
   public int weight;
   public Sprite sprite;

   public virtual void UseItem(Player player)
   {
      throw new NotImplementedException();
   }
}


[CreateAssetMenu(menuName = "Items/Create Potion")]
public class Potion : Item
{
   public int healingPower;
   public int manaPower;

   public override void UseItem(Player player)
   {
      Debug.Log(string.Format("You drank a {0}.", this.name));

      player.health += this.healingPower;          
      player.mana += this.manaPower;
   }
}

[CreateAssetMenu(menuName = "Items/Create Summon Orb")]
public class SummonOrb : Item
{
   public GameObject summonedCreaturePrefab;

   public override void UseItem(Player player)
   {
      Debug.Log(string.Format("You summoned a {0}", this.summonedCreaturePrefab.name));

      Instantiate(this.summonedCreaturePrefab);
   }
}

Then change your UseItem method in Player :然后在Player更改您的UseItem方法:

public class Player : MonoBehaviour
{
   public void UseItem()
   {
      if (this.itemInHand != null)
      {
         this.itemInHand.UseItem(this);
      }
   }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM