我正在尝试创建一个统一脚本,该脚本仅使用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;
}
}
}
答案 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);
注意:-要只播放一次声音,我又使用了一个布尔isPlayedOnce
我不确定这是否是最优化的方式。但肯定是一种更清洁的方式(通过代码)。