我怎样才能在“青铜”附近创建一个实例化我的边界,当它最接近时,我怎样才能在它周围创建一个实例化边界,而当它不再是最近的边界时,我怎样才能在它周围创建一个实例化我的边界?

How can I create a instantiate my border around a "bronze" when it is the closest and destroy the border when no longer the closest?

提问人:HarrisonO 提问时间:8/7/2020 更新时间:8/7/2020 访问量:37

问:

我已经坚持了一段时间。我想要的是将我的轮廓对象实例化到我的青铜基地游戏对象的位置,并在青铜基地不再离玩家最近时销毁它。

我愿意完全重启我的青铜脚本,如果这意味着我可以让它变得更容易。

提前致谢!

查找最接近的青铜脚本

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

public class FindBronze : MonoBehaviour
{
    void Update()
    {
        FindClosestBronze();
    }
    void FindClosestBronze()
    {
        float distanceToClosestBronze = Mathf.Infinity;
        Bronze closestBronze = null;
        Bronze[] allBronze = GameObject.FindObjectsOfType<Bronze>();

        foreach (Bronze currentBronze in allBronze)
        {
            float distanceToBronze = (currentBronze.transform.position - this.transform.position).sqrMagnitude;
            if (distanceToBronze < distanceToClosestBronze)
            {
                distanceToClosestBronze = distanceToBronze;
                closestBronze = currentBronze;
            }
            if (distanceToBronze > distanceToClosestBronze)
            {
                closestBronze.GetComponent<Bronze>().notSelected();
                
            }

            closestBronze.GetComponent<Bronze>().Selected();
        }
    }
}

青铜(包括轮廓)字体

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

public class Bronze : MonoBehaviour
{
    public bool isSelected = false;
    public Animator anim;
    [SerializeField]
    public GameObject selectedBox;
    public GameObject bronzeBase;
    private GameObject clone;
    // Update is called once per frame
    void Awake()
    {
        clone = (GameObject)Instantiate(selectedBox, bronzeBase.transform);

    }
    public void Selected()
    {
        if (!isSelected)
        {

           clone = (GameObject)Instantiate(selectedBox, bronzeBase.transform);
            isSelected = true;

        }
        
        else
        {
            Destroy(clone);
            isSelected = false;
        }
    }
    public void notSelected()
    {
       
        Destroy(selectedBox);
    }   

}
C# Unity-游戏引擎

评论


答:

1赞 derHugo 8/7/2020 #1

在你正在破坏预制件!BronzenotSelectedselectBox

您可能更想销毁该实例。clone


无论如何,我会建议一些我会做不同的事情

  • 而不是一直只使用InstantiateDestroySetActive
  • 而不是在 HashSet 事件驱动的存储中使用它们:每个 Bronze 实例都会注册和注销自身FindObjectOfTypeUpdate
  • 取决于个人品味,但我会用它来找到最接近的实例Linq

这可能看起来有点像

public class Bronze : MonoBehaviour
{
    // Every instance of this component registers and unregisters itself here
    public static readonly HashSet<Bronze> Instances = new HashSet<Bronze>();

    [Header("References")]
    public Animator anim;
    [SerializeField] private GameObject selectedBox;
    [SerializeField] private GameObject bronzeBase;

    [Header("Debugging")]
    [SerializeField] bool _isSelected = false;

    private GameObject clone;

    // Have a property for the selection
    public bool IsSelected
    {
        // when something reads this property return _isSelected
        get => _isSelected;
        // This is executed everytime someone changes the value of IsSelected
        set
        {
            if(_isSelected == value) return;

            _isSelected = value;

            clone.SetActive(_isSelected);
        }
    }

    // Update is called once per frame
    void Awake()
    {
        // Instantiate already returns the type of the given prefab
        clone = Instantiate(selectedBox, bronzeBase.transform);

        // Register yourself to the alive instances
        Instances.Add(this);
    }

    private void OnDestroy ()
    {
        // Remove yourself from the Instances
        Instances.Remove(this);
    }
}

然后使用它

using System.Linq;

public class FindBronze : MonoBehaviour
{
    private Bronze currentSelected;

    private void Update()
    {
        UpdateClosestBronze();
    }

    void UpdateClosestBronze()
    {
        if(Bronze.Instances.Count ==0) return;

        // This takes the instances
        // orders them by distance ascending using the sqrMagnitude
        // of the vector between the Instance and you
        // sqrMagnitude is more efficient than Vector3.Distance when you only need to compare instead of the actual distance
        // then finally it takes the first item 
        var newClosest = Bronze.Instances.OrderBy(b => (b.transform.position - transform.position).sqrMagnitude).First();

        // skip if the result is the same as last time
        if(newClosest == currentSelected) return;

        // otherwise first deselect the current selection if there is one
        if(currentSelected)
        {
            currentSelected.IsSelected = false;
        }
   
        // Then set the new selection     
        currentSelected = newSelected;
        currentSelected.IsSelected = true;
    }
}