Unity Engine - 通过碰撞实例化预制件

时间:2018-05-29 02:30:09

标签: c# unity3d collision-detection

我有一个名为播放器的GameObject。 附加到播放器有一个名为播放器的脚本组件(相同) 在Player的脚本中,我有一个名为 _weaponPrefab (GameObject类型)的字段

在Inspector中,我可以轻松地拖动和放大从_weaponPrefab变量中的Prefab文件夹中删除任何预制件。

到目前为止一切顺利。我要归档的是:能够基于 Collision2D 添加我的预制件。因此,如果我的玩家与预制件碰撞,让我们说一把剑,该剑的预制件将自动附加并插入到玩家脚本内的_weaponPrefab字段中。

在我的播放器脚本下面:

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

public class Player : MonoBehaviour
{
    [SerializeField] private float _speed = 5.0f;
    [SerializeField] private float _fireRate = 0.2f;
                     private bool _canFire = true;


    [SerializeField] private GameObject _weaponPrefab; <- to populate runtime


    // Use this for initialization
    void Start ()
    {
        transform.position = Vector3.zero;
    }

    // Update is called once per frame
    void Update ()
    {
        if (Input.GetKeyDown(KeyCode.Space) && _canFire)
            StartCoroutine(Shoot());
    }


    void OnTriggerEnter2D(Collider2D other)
    {
        //here i don't know how to continue.

    }

    public IEnumerator Shoot()
    {
        _canFire = false;
        Instantiate(_weaponPrefab, transform.position + new Vector3(0, 1, 0), Quaternion.identity);
        yield return new WaitForSeconds(_fireRate);
        _canFire = true;
    }
}

编辑:我刚刚写了一篇关于我不知道如何继续的评论。

3 个答案:

答案 0 :(得分:1)

当您实例化GameObject时,您需要传递基本上3个参数(但并非所有参数都是强制性的,check):

  • 预制件
  • 职位
  • 轮换

假设你手中或角色后面有一个占位符,一旦收集到那里就会保留武器。这个占位符可以是一个空的游戏对象(没有预制附件,但会有一个transform.position组件)

现在让我们假设你在场景中有一个武器列表,其中包含预制件和每个武器的不同标签。然后你可以做这样的事情:

GameObject weapon;
GameObject placeholder;

public Transform sword;
public Transform bow;
...


void OnTriggerEnter2D(Collider2D other)
{
    //You can use a switch/case instead
    if(other.gameObject.tag == "sword"){
        Instantiate(sword, placeholder.transform.position, Quaternion.identity);
    }else if(other.gameObject.tag == "bow"){
        Instantiate(bow, placeholder.transform.position, Quaternion.identity);
    }...

}

答案 1 :(得分:1)

有很多方法可以达到你想要的目的。

我的建议最初可能超出了您的舒适范围,但它会为您提供最大的灵活性,并最终轻松编程/设计/维护您的游戏(在我看来)。

首先制作一个可编写脚本的对象(what is a scriptable object and how do i use it?

using UnityEngine;
using System.Collections;
using UnityEditor;

public class Item
{
    [CreateAssetMenu(menuName = "new Item")]
    public static void CreateMyAsset()
    {
        public GameObject prefab;
        // you can add other variables here aswell, like cost, durability etc.
    }
}

创建一个新项目(在Unity,资产/新项目中)

然后创建一个可以容纳该项目的monobehaviour脚本。在你的情况下,我们将它命名为“Pickup”。

public class Pickup : MonoBehaviour
{
    public Item item;
}

最后在您的播放器脚本中,将您的TriggerEnter更改为:

void OnTriggerEnter2D(Collider2D other)
{
    if(other.GetComponentInChildren<Pickup>())
    {
        var item = other.GetComponentInChildren<Pickup>().item;
        _weaponPrefab = item.prefab;
    }

}

答案 2 :(得分:0)

我要做的是先从资源文件夹Dictionary<string, GameObject>加载预制件。

首先,我使用Start方法中的所有武器预制件填充字典,并将对象的标记作为键。然后在OnTriggerEnter2D我检查标签是否在字典中,然后我从那里实例化它。

看看代码:

private Dictionary<string, GameObject> prefabs;

// Use this for initialization
void Start () {
    var sword = (GameObject) Resources.Load("Weapons/sword", typeof(GameObject));
    prefabs.Add("sword", sword);
    // Add other prefabs
};

void OnTriggerEnter2D(Collider2D other)
{
    if (prefabs.ContainsKey(other.tag))
        Instantiate(prefabs[other.tag]);
}

注意:您的预制件需要位于Assets/Resources/Weapons文件夹中,因为我使用了Resources.Load("Weapons/sword", typeof(GameObject));