【问题标题】:how to play sound on Destroy()如何在 Destroy() 上播放声音
【发布时间】:2018-07-18 02:45:22
【问题描述】:

警告 - Unity3d 新手(大约工作 4 小时)但有编程经验。也可以长篇大论……

所以我有点遵循基本的“捡硬币”游戏教程。马上搞砸了,我想出了如何让硬币旋转/旋转,被捡起来等等。

我可以在唤醒/创建时播放声音,或者取消选中该框并调用

GetComponent<AudioSource>().Play();

在我的onTriggerEnter() 里面,我可以听到声音。

不幸的是,当下一行调用Destroy(gameObject) ...时,声音没有播放。我可以注释掉销毁调用,其他一切都可以正常工作,包括播放拾音器的声音,但是当硬币被“抓住”时,我确实需要从场景中移除硬币。

我可以将 AudioSource 移动到另一个不会被破坏的对象上,甚至可以创建一个 MyGame c# 脚本来控制所有声音、硬币计数、时间等。

但在我看来,我应该能够制作“硬币”资产,并且我将其导入到其中的任何项目都应该使用它自己的 AS、mp3 等等等等。

那么...如何创建一个独立对象,当它与它碰撞时播放声音然后Destroy()s 本身?

我的完整 Coin.cs 文件 - 它附加到通过调整 Column 3D 类型对象大小制作的 Coin。附加到硬币的音频源,如果对Destroy() 的调用被注释掉,则可以正常播放。为 Linux 运行最新的 Unity3d Beta(抱歉,没有 Mac 或 Win 机器,它在 virtualbox 中很烂)。不知道如何发布项目信息等,但如果需要请告诉我...

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

public class Coin : MonoBehaviour {

    public float rotate_speed=200f;

    // Use this for initialization
    void Start () {
    }

    void OnTriggerEnter(Collider Col){
        if(Col.CompareTag("Player")){
            Player.gotCoin();
            GetComponent<AudioSource>().Play();
            Destroy(gameObject);
        }
    }

    void Update () {
        // make coin tumble
        transform.Rotate(Vector3.left, rotate_speed * Time.deltaTime);
        transform.Rotate(Vector3.back, rotate_speed * Time.deltaTime);
        transform.Rotate(Vector3.up, rotate_speed * Time.deltaTime);
    }
}

【问题讨论】:

    标签: unity3d


    【解决方案1】:

    如果你真的想用对象独立包含音频,你可以尝试类似的方法:

    public class Coin : MonoBehaviour
    {
        // A generic Collider... You can be more specific if you want.
        public Collider collider;
    
        // Reference your renderer here.
        public MeshRenderer renderer;
    
        // Reference you AudioSource here.
        public AudioSource audioSource;
    
        public float rotate_speed = 200f;
    
        private bool isActive = true;
    
        void OnTriggerEnter ( Collider Col )
        {
            if ( Col.CompareTag ( "Player" ) )
            {
                Player.gotCoin ( );
                audioSource.Play ( );
                isActive = false;
                collider.enabled = renderer.enabled = false;
            }
        }
    
    
        void Update ( )
        {
            if ( isActive )
            {
                // make coin tumble
                transform.Rotate ( Vector3.left, rotate_speed * Time.deltaTime );
                transform.Rotate ( Vector3.back, rotate_speed * Time.deltaTime );
                transform.Rotate ( Vector3.up, rotate_speed * Time.deltaTime );
            }
            else
            {
                // If the coin is "dead", we check to see if the audio is still playing.
                // If not, we destroy the object.
                if ( !audioSource.isPlaying )
                    Destroy ( gameObject );
            }
        }
    }
    

    本质上,代码应该关闭对撞机,这样您就不会重新触发捡起同一个硬币,并关闭渲染器,所以它不会显示在屏幕上。就玩家而言,它已经不存在了。

    虽然.. 我仍然只使用音频管理器,并使用“硬币”池(而不是销毁),因为“硬币”的数量通常很多。但那是另一回事了。

    【讨论】:

    • 确实如此。如果这是纯 Java,我会有一个包含玩家实例和硬币实例数组的游戏类......非常感谢您的快速回答!
    • 为什么你认为你不能?您会惊讶于 Unity 中“纯”编码的使用效果如何。使用集中管理器意味着您不会在每个 GameObject 上调用 Unity 事件方法,例如 Update()。这可能相当于相当多的方法调用。在 Manager 中实现时,会在 manager 的 Update() 方法上调用一次。
    • @ivanivan 例如,看到rotate_speed * Time.deltaTime?您可以在硬币管理器中计算一次,然后将该值应用于所有硬币实例,而不是为每个硬币游戏对象计算 3 次。这只是一个即时优化。
    猜你喜欢
    • 1970-01-01
    • 2016-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多