So i am trying to apply an audio source onto a game object upon destroying it.
I can add the Audio Source component fine with the script but i am unable to load the audio file onto it.
The audio source component just says "None (Audio Clip)"
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BlockScript : MonoBehaviour
{
void OnMouseDown(){
if(this.gameObject.GetComponent<AudioSource>() == null) {
AudioSource blockBreakSound = this.gameObject.AddComponent<AudioSource>();
blockBreakSound.clip = Resources.Load("Assets/Sounds/BlockBreakingSound.wav") as AudioClip;
blockBreakSound.Play();
Destroy(this.gameObject, blockBreakSound.clip.length);
} else {
this.gameObject.GetComponent<AudioSource>().Play();
Destroy(this.gameObject, this.gameObject.GetComponent<AudioSource>().clip.length);
}
}
}
I am not receiving any errors so i am having a hard time figuring out what the problem is.
I can apply the audio file manually onto the game object / prefab i am spawning, but as i am trying to optimize it somewhat i dont want hundreds of game object with the audio file on them to begin with but rather put them on the object upon trying to destroy them
As #Hellium was really nice to point out i had missed the fact that i should keep my files in a folder called Resources to actually grab them with Resources.Load();
Thanks for the fast help :)
Related
I'm a beginner and this is my first post here so please let me know if I could do anything better.
Using PUN 2 in Unity, I'm trying to return a connection error message when the user attempts to connect to a Photon server but fails.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement; //Library that provides utilities for scene management
using Photon.Pun; //Library for Photon, provides networking utilities
using Photon.Realtime; //Helps solve problems relating to matchmaking and fast communication
using UnityEngine.UI; //
public class MenuMan : MonoBehaviourPunCallbacks
{
public override void OnDisconnected(DisconnectCause cause) //Callback for when device fails to connect to server. Parameter 'cause' is the cause of this failure
{
Debug.Log("failed :("); // FOR DEBUGGING
Debug.Log(cause); //Prints in the console the cause of this connection failure
DisplayErrorMessage();
}
public Text Message;
public string MessageValue = " ";
public void DisplayErrorMessage() //Method that displays a connection error message to the user
{
SceneManager.LoadScene("Character Select Menu"); //Ensures user is on the Character Select menu
MessageValue = "AAAAAAA";
//Message.text = MessageValue;
Debug.Log(Message.text);
Debug.Log(MessageValue);
}
}
When I run this code, the text "AAAAA" flashes for a second, then disappears. Through testing I found out this is because the message displays first for some reason, and only after does the scene change thus resetting the text.
I tried using coroutines to delay MessageValue from being altered until the scene changed:
public override void OnDisconnected(DisconnectCause cause) //Callback for when device fails to connect to server. Parameter 'cause' is the cause of this failure
{
StartCoroutine(GoToCSM());
DisplayErrorMessage();
}
IEnumerator GoToCSM()
{
Debug.Log("cor started");
SceneManager.LoadScene("Character Select Menu")
yield return new WaitForSeconds(3);
DisplayErrorMessage();
Debug.Log("Done");
}
public Text Message; //Initialises a 'Text' type object, which will be set to the Connection fail message
static string MessageValue = " "; //Initialises a string which will be written to the 'text' component of the above object
public void DisplayErrorMessage() //Method that displays a connection error message to the user
{
MessageValue = "AAAAAAA"; //Writes the string to be displayed to MessageValue
Message.text = MessageValue; //Sets the above text to the 'text' component of the Message object, thus displaying it on the screen
}
However the coroutine never goes past the yield statement. It just stops at the yield statement and doesn't continue (even the Debug.Log("Done") doesn't get logged).
But when I tried switching some things round and put SceneManager.LoadScene("Character Select Menu") beneath the yield statement, that was executed just fine, as well as the debug statement below. I have no idea why this could be, and am very confused.
This was meant to be an extremely simple 10 minute task and I've wasted days trying to figure out what to do now. Any help would be extremely greatly appreciated. Thank you!
When switching scenes the object running the coroutines gets destroyed. Which results in it never executing the delayed code in the coroutines, this also applies when loading the same scene as you have currently loaded.
Unity reloads the whole scene, it resets everything!
This is also the reason why you see the text flashing for a few seconds. You set the text of some component in your scene, then unity reloads it and its reset.
SceneManager.LoadScene is not instant it just tells unity to start loading the Scene and then switching to it when ready.
Which by the way is not a very performant thing to do and should only be done when you need to really reset it.
If you want to pass values such as cause of disconnection from one scene to another you should use static variables.
These are not stored in objects(that get deleted on scene load). They are static and get saved when switching scenes.
It would help if you shared some more details about the structure of your project. That can help us find a solution that suits your needs.
I'm new to C# and Unity, but I'm trying to code an app with Unity which would play my customer's 3D Side by Side VR video. I'm using script from here https://docs.unity3d.com/ScriptReference/Video.VideoPlayer.html to get the video running and it works great, BUT it doesn't play as Side By Side VR video, but just a flat video with two screens for both eyes.
UnityEngine.Video has Video3DLayout.SideBySide3d enumeration (https://docs.unity3d.com/ScriptReference/Video.Video3DLayout.html) that could solve the problem, but I don't know what is the right syntax for that. Here is the code I have tried:
using UnityEngine;
using System.Collections;
public class Movie : MonoBehaviour{
enum Video3DLayout {No3D, SideBySide3D, OverUnder3D};
void Start(){
Video3DLayout myLayout;
myLayout = Video3DLayout.SideBySide3D;
// Will attach a VideoPlayer to the main camera.
GameObject camera = GameObject.Find("Main Camera");
// VideoPlayer automatically targets the camera backplane when it is added
// to a camera object, no need to change videoPlayer.targetCamera.
var videoPlayer = camera.AddComponent<UnityEngine.Video.VideoPlayer>();
// Play on awake defaults to true. Set it to false to avoid the url set
// below to auto-start playback since we're in Start().
videoPlayer.playOnAwake = false;
// By default, VideoPlayers added to a camera will use the far plane.
// Let's target the near plane instead.
videoPlayer.renderMode = UnityEngine.Video.VideoRenderMode.CameraNearPlane;
// Set the video to play.
videoPlayer.url = "movie.mp4";
// Start playback. This means the VideoPlayer may have to prepare (reserve
// resources, pre-load a few frames, etc.). To better control the delays
// associated with this preparation one can use videoPlayer.Prepare() along with
// its prepareCompleted event.
videoPlayer.Play();
}
}
I have feeling that I'm introducing the enumerations wrong way and I hope that someone could guide me to right direction. I have tried to use this tutorial https://unity3d.com/learn/tutorials/topics/scripting/enumerations to understand more about enumerations, but this way my code is not working.
There's 2 reasons why it isn't working. You're creating a new enum, instead of using the UnityEngine.Video.Video3DLayout enum. Also you're not assigning myLayout to the videoPlayer.
using UnityEngine;
using System.Collections;
using UnityEngine.Video;
public class Movie : MonoBehaviour
{
public Video3DLayout myLayout;
void Start()
{
// Will attach a VideoPlayer to the main camera.
GameObject camera = GameObject.Find("Main Camera");
// VideoPlayer automatically targets the camera backplane when it is added
// to a camera object, no need to change videoPlayer.targetCamera.
var videoPlayer = camera.AddComponent<UnityEngine.Video.VideoPlayer>();
videoPlayer.targetCamera3DLayout = myLayout;
// Play on awake defaults to true. Set it to false to avoid the url set
// below to auto-start playback since we're in Start().
videoPlayer.playOnAwake = false;
// By default, VideoPlayers added to a camera will use the far plane.
// Let's target the near plane instead.
videoPlayer.renderMode = UnityEngine.Video.VideoRenderMode.CameraNearPlane;
// Set the video to play.
videoPlayer.url = "movie.mp4";
// Start playback. This means the VideoPlayer may have to prepare (reserve
// resources, pre-load a few frames, etc.). To better control the delays
// associated with this preparation one can use videoPlayer.Prepare() along with
// its prepareCompleted event.
videoPlayer.Play();
}
}
I'm trying to make a multiplayer game and in my program there is a spawnSpots code that I made and it's saying that it doesn't exist but it clearly does.
Here's the code:
void Start()
{
spawnSpots = GameObject.FindObjectOfType<SpawnSpot>();
}
Then there is:
if(spawnSpots == null)
{
Debug.LogError("No Spawns Placed.");
return;
}
SpawnSpot mySpawnSpot = spawnSpots[Random.Range (0, spawnSpots.length)];
So everytime the word spawSpots is written, the error is saying:
Severity Code Description Project File Line Suppression State
Error CS0103 The name 'spawnSpots' does not exist in the current context Multiplayer-FPS.CSharp C:\Users\desha\Documents\Multiplayer-FPS\Assets\NetworkManager.cs 15 Active
How can I fix this?
Ok if you are setting up a networked multiplayer game then you will need to have a NetworkStartPosition component on each of your spawn point in the scene.
It is also worth noting that the NetworkManager you would need in your scene also has some spawn settings. Including a spawn method, which if you select "round robin" will randomly spawn players at each of your NetworkStartPositions for you.
Hope this helps.
Here is a link to an excellent video covering the basics of network multiplayer. It is by far the most useful I have found. UnityNetworkTutorial
You are using GameObject.FindObjectOfType incorrectly, it looks like you want to set up an array then pick a random one. Lookup arrays, how to add to the array.
find object of type: https://docs.unity3d.com/ScriptReference/Object.FindObjectOfType.html
Heey,
We created a game with Monogame but we got the following problem.
We got a themesong that plays when you have loaded the game now is the problem that the themesong sometimes plays but sometimes just doesn't. We convert it by the XNA pipeline to a wma and load it into our game with the .xnb together but just sometimes the music doesn't wanna start.
We just use the standard code for starting a song and all of this code does fire.
internal void PlayBackgroundMusic()
{
if (MediaPlayer.GameHasControl)
{
MediaPlayer.Volume = mainVolume;
MediaPlayer.Play(backgroundMusic);
MediaPlayer.IsRepeating = true;
}
}
We also use SoundEffects but these work 100% of the time it's only the song that won't play everytime you start. Windows RT runs it fine by the way.
Make sure that the debugger gets into the if statement through debugging (or remove the statement temporarily). Another possibility might be that the function is running before the game is fully initialized. You could try delaying the function until the game has been fully loaded.
PS: I can't comment on questions yet so here's an answer.
Edit:
Alright, after some messing around with the Song class and looking in the implementation in MonoGame I came to the conclusion that the SoundEffect class is easier to use and better implemented.
backgroundSound = Content.Load<SoundEffect>("alarm");
protected override void BeginRun()
{
// I created an instance here but you should keep track of this variable
// in order to stop it when you want.
var backSong = backgroundSound.CreateInstance();
backSong.IsLooped = true;
backSong.Play();
base.BeginRun();
}
I used this post: using BeginRun override to play the SoundEffect on startup.
If you want to play a song, use the Song class. But make sure you are using ".mp3" instead of ".wma" before converting them into ".xnb".
backgroundMusic = Content.Load<Song>("MainTheme");
MediaPlayer.Play(backgroundMusic);
MediaPlayer.IsRepeating = true;
See MSDN.
I know I can reference XNA for the SoundEffect class and that's what I've been doing so far but I was wondering if there was a better way than what I've been doing.
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using (var stream = TitleContainer.OpenStream("test.mp3"))
{
var effect = SoundEffect.FromStream(stream);
FrameworkDispatcher.Update();
effect.Play();
}
For my test app I have 20 sounds each 1 second long that I want to play once button are pressed. I'm playing around with different techniques but if possible I'd like to know how professionals go about doing this before I commit in making a sound effect based app. Little things such as loading the sound effect first or loading it the instance the button is pressed would be helpful.
Thanks.
If I were you I would use PhoneyTools SoundEffectPlayer
This class is used to play SoundEffect
objects using the XNA integration. The
player must live long enough for the
sound effect to play so it is common
to have it scoped outside a method.
For example:
public partial class MediaPage : PhoneApplicationPage
{
// ...
SoundEffectPlayer _player = null;
private void playButton_Click(object sender, RoutedEventArgs e)
{
var resource = Application.GetResourceStream(new Uri("alert.wav", UriKind.Relative));
var effect = SoundEffect.FromStream(resource.Stream);
_player = new SoundEffectPlayer(effect);
_player.Play();
}
}
I think a good example would be the official sample on AppHub. It demonstrates how to play multiple sounds. You can directly download the sample from here.
This sample demonstrates how to use
the XNA Framework's SoundEffect and
SoundEffectInstance classes to play
multiple sounds simultaneously in a
Silverlight application for Windows
Phone. It also shows a simple way to
set up a DispatchTimer to call
FrameworkDispatcher.Update in order to
simulate the Game loop for the XNA
Framework's internals. Finally, it
shows how to load a wave audio file
into a Stream that can be played by
the SoundEffect classes.