I'm making a VR application for iOS/Android.
I just bought Easy Movie Texture, using latest Unity version.
I can play one of the video. But I don't know how to play multiple videos.
For example, how do I make a cardboard tap trigger to change a movie?
I’m using the Sphere Example.
I created a gameobject, inside it’s update() function has a if(Carboard.SDK.Triggered) that I want to change the target parameter in sphere (Media Player Control Script). (Change the video)
How do I access this object? Where Exactly that object is created?
In short, mediaPlayerCtrl.Load(movieName) changes the movie. The movie must be in StreamingAssets for this to work properly (SD card is possible on Android, but requires more effort).
As you have issues with locating your MediaPlayerCtrl instance, here's an easy solution. Add this script to an example from Easy Movie Texture and use the ChangeMovie method.
using UnityEngine;
public class EMTChangeFile : MonoBehaviour
{
// drag an instance of Media Player Ctrl or leave empty for autodetection
public MediaPlayerCtrl mediaPlayerCtrl;
void Awake ()
{
if (mediaPlayerCtrl == null)
{
mediaPlayerCtrl = FindObjectOfType<MediaPlayerCtrl>();
if (mediaPlayerCtrl == null)
throw new UnityException("No Media Player Ctrl object in scene");
}
}
public void ChangeMovie(string movieName, bool autoplay = true)
{
mediaPlayerCtrl.Stop();
mediaPlayerCtrl.Load(movieName);
if(autoplay)
mediaPlayerCtrl.Play();
else
mediaPlayerCtrl.Stop();
}
}
Related
I have a game wehre you are a cube and you dodge obstacles, I just implemented the ability to change the color of the cube like changing skin. I did that by assigning a different material to the player when he presses "2".
Here is the script:
void Update()
{
if (Input.GetKeyDown("2"))
{
Object.GetComponent<MeshRenderer>().material = Material1;
}
}
When you die the scene resets and when you win a new scene is loaded, I would like the game to remember the material change even after the scene is reset or a new scene is loaded. I have done some research and found something called "PlayerPrefs" and I have been playing around with it but nothing even got close to working and I didn't really understand what i was doing.
I really want to understand how this works becuase I know i will be using it alot when making games. Can someone help me understand?
Thanks.
Create one gameobject and apply this script
public class SavingMaterial : MonoBehaviour
{
public static SavingMaterial instance;
public Material mat;
void Awake()
{
if(instance == null)
{
instance = this;
DontDestroyOnLoad(base.gameObject);
}
else
{
Destroy(base.gameObject);
}
}
public void StoreMaterial(MeshRenderer mesh)
{
mat = mesh.material;
}
}
When you want to store material call this function like this
SavingMaterial.instance.StoreMaterial(you meshrenderer component);
and when you need this material just get from this class like this
material = SavingMaterial.instance.mat;
and note that if you quit the game you loose saved material as it is store in variable otherwise scene change and reset won't affect it.
you only save int,string and bool in playerprefs. you have to store values of materials into string and then save this string into playerprefs.
alternatively you can assign this material to local variable and set that script on Dontdestroyonload so it will not reset as scene is destroy or reset.
I'm working on a multiplayer game and I'm encountering a issue when 2 players are loading the same level using PhotonNetwork.LoadLevel().
When I start the game alone, I can control my player and everything is fine. But when we are 2 players, Player A is controlling Player B and vice-versa.
I check a lot of links on the internet these past few days, and I learned the concept of PhotonNetwork.IsMine which I thought would solve all of my problem but it seems to not working with me. Also, I'm using the new input system of Unity but I don't think the issue come from here.
Basically, what I'm doing is:
Instantiate a player (this happened twice since I have 2 players) which have a PlayerManager
Player Manager Get Instance of the local player and synchronize camera with the local player only if isMine = true
CameraManager creates input manager if the script is linked to the local player by using isMine
Link the main camera to this script when the gamemanager request it
Update camera rotation only when isMine is true (second protection)
Here is a piece of my code:
GameManager.cs (Holding by a Scene Object, so it is initially instantiated for everyone with the scene)
void Start()
{
if(PlayerManager.LocalPlayerInstance == null)
{
//Get player's team
string team = (string)PhotonNetwork.LocalPlayer.CustomProperties["Team"];
int indexPlayer = GetSpawnPosition();
//Spawn player depending on its team and its index in the players pool
if (team.Equals("Spy"))
{
PhotonNetwork.Instantiate(this.spyPrefab.name, SpySpawns[indexPlayer].position, SpySpawns[indexPlayer].rotation);
}
else if (team.Equals("Defender"))
{
PhotonNetwork.Instantiate(this.defenderPrefab.name, SpySpawns[indexPlayer].position, SpySpawns[indexPlayer].rotation);
}
}
}
PlayerManager.cs (Holding by the player, so not initially instantiated with the scene)
void Awake()
{
//Keep track of the localPlayer to prevent instanciation when levels are synchronized
if (photonView.IsMine)
{
LocalPlayerInstance = gameObject;
}
//Don't destroy this gameobject so it can survives level synchronization
DontDestroyOnLoad(gameObject);
}
private void Start()
{
//Get Manager of the camera of the player and attach to the local player
CameraLookFPS cameraFPSManager = gameObject.GetComponent<CameraLookFPS>();
if (cameraFPSManager != null)
{
//Ensure that we the local player is controlling its own camera
if(photonView.IsMine == true)
{
cameraFPSManager.SynchronizeWithLocalPlayer();
}
}
else
Debug.Log("This player is missing the CameraLookFPS component");
}
CameraManager.cs (Holding by the player, so not initially instantiated with the scene)
private void Start()
{
//Synchronize camera with local player on start for debug
if(SynchronizeOnStart)
{
SynchronizeWithLocalPlayer();
}
//Bind input for controlling the camera
BindingInput();
}
private void BindingInput()
{
// Prevent control is connected to Photon and represent the localPlayer
if (photonView.IsMine == false && PhotonNetwork.IsConnected == true)
{
return;
}
else
{
//Get Components
Input_Master = new InputMaster();
//Enable
Input_Master.Enable();
//Input binding
Input_Master.Player.Look.performed += context => MoveCamera(context);
Input_Master.Player.Look.Enable();
}
}
public void SynchronizeWithLocalPlayer()
{
if (photonView.IsMine == false && PhotonNetwork.IsConnected == true)
{
return;
}
Player_Camera = Camera.main.transform;
isSynchronized = true;
}
I tried to be clear enough, tell me if something is bad explained. I'll continue my research on my side and I'll keep you in touch if I find something.
Thanks in advance for your help!
Adrien
I finally found my solution. It appears that I already read about it but I have failed when trying to solve it.
So, like a lot of people, it is a Camera issue.
What I did is:
Create a game object holding the camera and put it as a child of the player gameobject
Deactivate the game object holding the camera
When instantiating the player, check if the player is the local player, using PhotonNetwork.IsMine. If yes, activate the gameobject holding the camera through script
If you have questions, send me a message!
Adrien
I have having difficulty obtaining and printing the filename of a video clip that I am playing in my Unity project.
I have asked UnityAnswers and a few other forums but no one seems to know so I thought I'd try my luck here. I have been researching the Unity scripting manual but again there is not much to go on since I am not THAT experienced with unity. I already have a script that is used to handle the videoPlayer functions but I was creating a separate script which referenced the videoPlayer one. The only purpose of this script is to print the name of a video file onto the console.
path = videoClip.originalPath;
if(path != null)
{
print(path);
}
}
Bear in mind that I am not even sure that is the correct code to use. I was going to using fileInfo but I'm not sure that would compile anything.
originalPathreturns the location of the video you are playing. To get the current video clips' name, just add name tag to it.
void Start()
{
string nameOfVideo = vpClip.name; //vpClip is video clip, not video player component
Debug.Log("name of the video : "+nameOfVideo);
}
using System.IO;
public class VideoManager : MonoBehaviour
{
public TMP_InputField videoName;
public VideoPlayer videoPlayer;
void Update()
{
if (videoPlayer.isPlaying)
{
videoName.text = Path.GetFileName(videoPlayer.url);
}
}
I've been working on a simple 2D game in unity and it just has three scenes, the start scene, the game scene, and the game over scene. I want to display the score from the game in the game over screen. I created a score manager game object in the game scene that uses the DontDestroyOnLoad() function to carry it over into the game over screen and I gave it access to the score which is managed by the game manager. I've been debugging my code and the score is translated over into the score manager and is maintained when the game over screen loads, but for some reason it won't let me update the score text object. Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ScoreManager : MonoBehaviour {
public static ScoreManager Instance;
private GameController gameController;
private int scoreInstance;
private Text scoreText;
// When scene is first loaded
void Awake() {
this.InstantiateController();
}
// Use this for initialization
void Start () {
GameObject gameControllerObject = GameObject.FindWithTag("GameController");
if (gameControllerObject != null)
{
gameController = gameControllerObject.GetComponent<GameController>();
}
GameObject scoreTextObject = GameObject.FindWithTag("ScoreText");
if (scoreTextObject != null)
{
scoreText = scoreTextObject.GetComponent<Text>();
}
scoreInstance = 0;
scoreText.text = "";
}
// Update is called once per frame
void Update () {
scoreInstance = gameController.score;
Debug.Log("Score: " + scoreInstance.ToString());
scoreText.text = scoreInstance.ToString();
}
private void InstantiateController ()
{
if (Instance == null)
{
Instance = this;
DontDestroyOnLoad(this);
}
else if (this != Instance)
{
Destroy(this.gameObject);
}
}
}
So I tried to programmatically gather the "score text" ui component in the start function because I figured I can't just make it public and drag in the text component because the score manager is actually in a different scene than the score text object. I also tried adding this whole bit of code to gather the text component into the update function so that it can do that when the score manager is actually a part of game over screen. Nothing seems to work and I have no idea why. Can anybody please help me with this? Also I keep getting a "NullReferenceException: Object reference not set to an instance of an object" error. Thanks in advance for any help.
Unity Start function is only called the first time the script is enabled, i.e. not every time the scene changes for a DontDestroyOnLoad object.
So if you need to wire up some changes after a scene change, you need to either detect the scene change, or have an object that starts in that scene trigger the code you want to run.
Having another object on the new scene trigger things is easy and pretty fool-proof, but there's a builtin function you can add to your other objects:
void OnLevelWasLoaded(int currentLevel)
{
}
This will be called on level changes, and give you the level's number (not name sadly). However, the above is deprecated and they want you to use Unity's SceneManager, so the proper way to set this up is now:
Unity 5 OnLevelWasLoaded?
Start()
{
SceneManager.sceneLoaded += this.OnLoadCallback;
}
void OnLoadCallback(Scene scene, LoadSceneMode sceneMode)
{
// you can query the name of the loaded scene here
}
I'm working with Unity 5.3 with C# as code editor
These are what I have :
I have 2 scenes in my project : home and options. I have bg object on both scenes. Both bg objects have Audio Source component, which contains same background music that play on awake. I don't use any codes for these background musics, I only click the Add Component button from Unity and add Audio Source.
This is what I want :
Options scene can toggle the background music on/off for all scenes. Therefore, there are btnOn and btnOff in Options scene.
This is my code in Audio Manager.cs :
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class AudioManager : MonoBehaviour {
public Button btnOn;
public Button btnOff;
// Use this for initialization
void Start () {
btnOn = GetComponent<Button>();
btnOff = GetComponent<Button>();
btnOn.onClick.AddListener(() => PlayAudio());
btnOff.onClick.AddListener(() => StopAudio());
}
void PlayAudio()
{
AudioSource.volume = 0.5f;
}
void StopAudio()
{
AudioSource.volume = 0f;
}
}
This is the problem :
I have this error : An object reference is required to access non-static member UnityEngine.AudioSource.volume. Maybe, this is because I don't write public AudioSource audioSource in my code. But, if I write this, I have to add another audio in Get Component box, and I will have double Audio Source in one scene. What should I do? Thanks
As you have a bg object in both scenes and as your AudioManager isn't marked as [DontDestroyOnLoad] (then I assume you also have one AudioManager in both scenes), it's Start() function will fire each time you load a scene.
So you can declare a private AudioSource and get a reference of it by finding your bg object in your scene and calling GetComponent on it :
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class AudioManager : MonoBehaviour
{
public Button btnOn;
public Button btnOff;
private AudioSource audioSource;
// Use this for initialization
void Start()
{
btnOn = GetComponent<Button>();
btnOff = GetComponent<Button>();
btnOn.onClick.AddListener(() => PlayAudio());
btnOff.onClick.AddListener(() => StopAudio());
audioSource = GameObject.Find("bg").GetComponent<AudioSource>();
}
void PlayAudio()
{
audioSource.volume = 0.5f;
}
void StopAudio()
{
audioSource.volume = 0f;
}
}
The error is raised because you need to assign the property on an individual object; the volume is not shared between sources. For this reason you will either need a field to assign in the inspector, or get a reference with GetComponent.
While using different scenes for handling options is not wrong, it is a tad clumsy; the current scene has to be unloaded (destroying all object not marked as DontDestroyOnLoad and information associated with them), after which the options are loaded, to then load the previous scene. While unloading the music most likely stops playing, which, after loading, starts at the beginning again. Not mention any settings on these objects are lost (volume, change of track, etc.).
The afore mentioned DontDestroyOnLoad can help since you make your changes on the same object, but you will have to deal with duplicates each time a scene is loaded where such an object exists... you can use the function OnLevelWasLoaded (documentation is a tad lacking at the moment) as a moment to determine which objects to destroy.
Another point is that you currently have public Button fields. This allows the for the assignment of them via the inspector, but that is rather moot as you overwrite them in Start (new value being the first button component assigned to the same object). I would make these fields private, or at least make sure they are not assigned. But I'm getting slightly of topic on how to keep settings persistent between scenes.
Here is some code to give you an idea, but be warned it is untested as I currently have no access to an environment to test it. This solution uses an object which is persistent between scenes. Keep in mind that any connections established to this object via the editor are lost after another scene has loaded.
public class AudioManager : MonoBehaviour
{
private AudioSource source;
// Called regardless of whether the object is enabled or not.
// Should not be called in a new scene.
private void Awake()
{
// Protect this object from being destroyed so its volume
// is maintained between scenes.
DontDestroyOnLoad(this.gameObject);
source = GetComponent<AudioSource>();
}
public void DestroyPossibleDuplicates()
{
AudioManager[] managers = FindObjectsOfType(typeof(AudioManager)) as AudioManager[];
foreach (AudioManager manager in managers)
{
// Use something to determine whether a manager is a duplicate.
// It must not be this, but have something in common; a name perhaps?
if ((manager != this) && (manager.gameObject.name == this.gameObject.name))
{
// Destroy the duplicates so their sound won't interfere.
Destroy(manager.gameObject);
}
}
}
private void BindToInterface()
{
Slider[] sliders = FindObjectsOfType(typeof(Slider)) as Slider[];
foreach (Slider slider in sliders)
{
// Determine whether the specified slider should have effect on this object.
// If the slider's name contains this object's name assume it should.
if (slider.gameObject.name.indexOf(this.gameObject.name)!=-1)
{
slider.onValueChanged.addListener((float value)=>
{
// In this case a slider is used for more control over the volume.
// Different elements require other logic to function.
source.volume = value;
});
}
}
}
// If my memory serves correct this method is only called on objects
// that were in the scene before it started loading.
// Just to be safe, don't have it do anything depending on this difference.
private void OnLevelWasLoaded()
{
DestroyPossibleDuplicates();
BindToInterface();
}
}