Как определить, может ли инстанцированный сборник быть размещен в текущем местоположении или нет

Я использую Unity 5.5.0f3 с C #.

Мой prefab (деревянный забор) создается при моей мыши, когда я нажимаю кнопку пользовательского интерфейса и следую за мышью, пока я не щелкнул где-нибудь на сцене, чтобы разместить ее. Забор имеет коробчатый коллайдер.

В настоящее время забор может быть помещен пересекающимся и даже внутри всего остального на сцене прямо сейчас, и я хочу устранить эту проблему.

Я хотел бы, чтобы мой забор (и любые другие будущие сборники) проверял, пересекается ли он с коллайдером объекта, когда он следит за моей мышью и краснеет, если он есть, или же зеленый, если он не указывает, может ли он или не могут быть размещены там, и соответственно разрешить или запретить размещение.

Я читал, что нет никакого способа сделать это, используя transform.position, поскольку это по существу использует телепортацию на моем заборе. Я пытался использовать GetComponent<Rigidbody>().MovePosition(hit.point + positionOffset);, но при этом я получаю все виды странного поведения.

Ниже перечислены три сценария, которые я использую, чтобы это произошло:

Raycast Builder:

public class RaycastBuilder : MonoBehaviour {

    public GameObject defense;
    public Vector3 positionOffset;

    public bool IsPurchased = false;

    public float speed = 2f;

    Vector3 mousePosition;

    BuildManager buildManager;

    void Start ()
    {
        buildManager = BuildManager.instance;
    }

    void Update ()
    {
        GameObject defenseToBuild = buildManager.GetDefenseToBuild();
        if(defenseToBuild == null)
        {
            return;
        }

            //To get the current mouse position
            mousePosition = Input.mousePosition;

            Ray ray = Camera.main.ScreenPointToRay(mousePosition);
            RaycastHit hit;

            if (Physics.Raycast(ray, out hit, 1 << 8))
            {
            defenseToBuild.transform.position = hit.point + positionOffset;

            if (Input.GetKey(KeyCode.E))
                {
                    defenseToBuild.transform.Rotate(Vector3.up * speed * Time.deltaTime);
                }
            if (Input.GetKey(KeyCode.Q))
                {
                    defenseToBuild.transform.Rotate(-Vector3.up * speed * Time.deltaTime);
                }
        }

        if (Input.GetMouseButton(0)&& IsPurchased == true)
        {
            buildManager.SetDefenseToBuild(null);
            IsPurchased = false;
        }

        if(Input.GetKeyDown(KeyCode.Escape))
        {
            buildManager.SetDefenseToBuild(null);
            Destroy(defenseToBuild);
            IsPurchased = false;
        }
    }
}

Магазин:

public class Shop : MonoBehaviour {

    BuildManager buildManager;

    void Start ()
    {
        buildManager = BuildManager.instance;
    }

    public void PurchaseWoodenFence ()
    {
        Camera.main.GetComponent<RaycastBuilder>().IsPurchased = true;
        Debug.Log("Wooden Fence Started");
        buildManager.SetDefenseToBuild((GameObject)Instantiate(buildManager.woodenFencePrefab, Vector3.up, Quaternion.identity));
    }

}

Менеджер сборки

public class BuildManager : MonoBehaviour {

    public static BuildManager instance;

    void Awake ()
    {
        if (instance != null)
        {
            Debug.Log("More than one BuildManager in Scene!");
            return;
        }
        instance = this;
    }

    public GameObject woodenFencePrefab;

    private GameObject defenseToBuild;

    public GameObject GetDefenseToBuild ()
    {
        return defenseToBuild;
    }

    public void SetDefenseToBuild (GameObject defense)
    {
        defenseToBuild = defense;
    }

}
4 голоса | спросил MjercerGameDev 28 J000000Friday17 2017, 23:29:10

1 ответ


1

Я предлагаю использовать isTrigger свойство коллайдера вместо raycasting.

В основном создайте экземпляр объекта, который вы хотите разместить в своей сцене, с его isTrigger, установленным в true, и когда он помещен (щелчком мыши), установите isTrigger в false, чтобы заставить его работать как обычный коллайдер.

Изменить: привязка моего кода для демонстрации триггерного коллайдера. Кроме того, ознакомьтесь с записью документации по объединению коллайдерами .

using UnityEngine;

public class Builder : MonoBehaviour
{
    private int colliderCount = 0;

    private void Update()
    {
        TrackMouse();
        Debug.Log("Number blocking colliders: " + colliderCount);
    }


    private void TrackMouse()
    {
        var mousePosition = Input.mousePosition;

        Ray ray = Camera.main.ScreenPointToRay(mousePosition);
        RaycastHit hit;

        if (Physics.Raycast(ray, out hit, 1 << 8))
            transform.position = new Vector3(hit.point.x, hit.point.y, transform.position.z);
    }

    private void OnTriggerEnter(Collider other)
    {
        colliderCount++;
    }

    private void OnTriggerExit (Collider other)
    {
        colliderCount--;
    }
}
ответил ccld44 29 J000000Saturday17 2017, 00:41:08

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132