如何仅使用C#代码创建边界?

时间:2018-11-27 21:12:44

标签: c# unity3d

我正在尝试创建一个统一脚本,该脚本仅使用C#代码(无边界框)来检测玩家何时离开了某个区域。播放器离开后,我的代码应该可以播放声音,但是代码无法正常工作,并且我看不到逻辑上的错误。

预期行为

当玩家走出边界时,声音将播放一次。

实际行为

无论播放器在哪里,声音始终在播放。

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

public class EX2BoundaryDetect : MonoBehaviour {

    // create a GameObject to represent the player
    public GameObject playerObject;
    public bool leaveArea = false;

    // create an Audio-clip object. This assumes we drag a sound file onto the myclip box in the Inspector.
    public AudioClip myclip;

    // Use this for initialization
    void Start () {

        // associate playerObject with the player. This assumes the First Person Controller is name "player
        playerObject = GameObject.Find ("player");

        // get the actual Sound file from the Inspector
        GetComponent<AudioSource>().clip = myclip;

    }

    // Update is called once per frame
    void Update () {

        PlayAudio1();
        if (leaveArea) {
            GetComponent<AudioSource> ().Play ();
        }
    }

    public void PlayAudio1 () {

        // play the sound if the player is outside some boundaries

        if (transform.position.x > 10) {
            leaveArea = true;
        }

        if (transform.position.x < -29) {
            leaveArea = true;
        }

        if (transform.position.z > 10) {
            leaveArea = true;
        }

        if (transform.position.z < -29) {
            leaveArea = true;
        }

    }
}

3 个答案:

答案 0 :(得分:1)

leaveArea仅在类定义中设置为false。一旦设置为true,就永远不会再将其设置为false,并且一开始可能会在场景定义中无意中将其覆盖。

要解决此问题,请在false的开头将其设置为Update

void Update () {

    leaveArea = false;
    PlayAudio1();
    if (leaveArea) {
        GetComponent<AudioSource> ().Play ();
    }
}

另外,GetComponent是一项昂贵的操作,最好避免在Update中调用它。因此,您可能需要将其移到class属性中并在Start中设置一次:

private AudioSource audioSource;

void Start () {

    // associate playerObject with the player. This assumes the First Person Controller is name "player
    playerObject = GameObject.Find ("player");

    audioSource = GetComponent<AudioSource>();

    // get the actual Sound file from the Inspector
    audioSource.clip = myclip;

}

// Update is called once per frame
void Update () {

    leaveArea = false;
    PlayAudio1();
    if (leaveArea) {
        audioSource.Play ();
    }
}

答案 1 :(得分:0)

通过添加

使它现在可以正常工作
leaveArea = false;

转到Update方法。

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

public class EX2BoundaryDetect : MonoBehaviour {

    // create a GameObject to represent the player
    public GameObject playerObject;
    public bool leaveArea = false;

    // create an Audio-clip object. This assumes we drag a sound file onto the myclip box in the Inspector.
    public AudioClip myclip;

    // Use this for initialization
    void Start () {

        // associate playerObject with the player. This assumes the First Person Controller is name "player
        playerObject = GameObject.Find ("player");

        // get the actual Sound file from the Inspector
        GetComponent<AudioSource>().clip = myclip;

    }

    // Update is called once per frame
    void Update () {

        PlayAudio1();
        if (leaveArea) {
            GetComponent<AudioSource> ().Play ();
        }

        leaveArea = false;
    }

    public void PlayAudio1 () {

        // play the sound if the player is outside some boundaries

        if (transform.position.x > 10) {
            leaveArea = true;
        }

        if (transform.position.x < -29) {
            leaveArea = true;
        }

        if (transform.position.z > 10) {
            leaveArea = true;
        }

        if (transform.position.z < -29) {
            leaveArea = true;
        }



    }
}

答案 2 :(得分:0)

我认为以上答案仍然不能解决您的问题“当玩家离开边界时,声音将播放一次。”

我将分享一种更清洁的方式(可能已优化)

使用边界

使用Bounds https://docs.unity3d.com/ScriptReference/Bounds.html

创建我们自己的边界

Bounds的构造函数为Bounds(Vector3 center,vector3 size)

因此,在您的案例中,中心将为center = (-9.5f, 0, -9.5f)(中点公式),最后边界框的大小将为size = (39.0f, 0f, 39.0f)

我们转到代码部分

public class BoundsCheck: MonoBehaviour
{
    public bool isInside = false;
    public bool isPlayedOnce = false;
    private Bounds bounds;

    void Start()
    {
        bounds = new Bounds(new Vector3(-9.5f, 0, -9.5f), new Vector3(39.0f, 0f, 39.0f));
    }


    void Update()
    {
        CheckBounds();// play the sound if the player is outside some boundaries
        if (!isInside &&!isPlayedOnce)
        {
            Debug.Log("PLAY");
            isPlayedOnce = true;
        }
    }

    private void CheckBounds()
    {


        bool isInsideBound = bounds.Contains(transform.position);
        if (isInsideBound)
        {
            isInside = true;
            if (isPlayedOnce)
            {
                isPlayedOnce = false;
            }
        }
        else
        {
            isInside = false;
        }
    }
}


因此,我们可以使用bool isInsideBound = bounds.Contains(transform.position);

来检查变换的位置是否在边界内,而不是多个ifs。

注意:-要只播放一次声音,我又使用了一个布尔isPlayedOnce

我不确定这是否是最优化的方式。但肯定是一种更清洁的方式(通过代码)。