I need to use a Unity slider to change the time of an AudioSource. As now the slider is capable to display the time position the AudioSource is on, but I also need it to edit the position. Here's my code:
public Slider time;
public AudioSource audio;
// Start is called before the first frame update
void Start()
{
audio = GetComponent<AudioSource>();
}
// Update is called once per frame
void Update()
{
time.maxValue = audio.clip.length;
time.value = audio.time;
audio.time = time.value;
}
How can I do that?
public Slider slider;
private AudioSource audioS;
private void Awake()
{
audioS = GetComponent<AudioSource>();
}
void Update()
{
slider.maxValue = audioS.clip.length;
}
public void OnSliderValueChanged()
{
audioS.time = slider.value;
}
private void FixedUpdate()
{
slider.value = audioS.time;
}
Once you have this code in your file, simply go to your slider. All the way down in the properties panel, you will find "OnValueChanged" put your object with your script attached to it and simply choose your function. Your function will now be called everytime you change the value of the slider.
Related
Hello i have a problem with animation controller script used to play animations depending on which key is pressed
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AnimationController : MonoBehaviour
{
function UpdateAnimations()
{
if (Input.GetKeyDown(KeyCode.W))
{
animation.CrossFade("goup");
}
else if (Input.GetKeyDown(KeyCode.A))
{
animation.CrossFade("goleft");
}
else if (Input.GetKeyDown(KeyCode.D))
{
animation.CrossFade("goright");
}
else if (Input.GetKeyDown(KeyCode.S))
{
animation.CrossFade("godown");
}
}
void Start()
{
}
// Update is called once per frame
void Update()
{
UpdateAnimations();
}
It says that "Component.animation" is too old, and i should use GetComponent but i don't know how to
First of all you most probably mean void instead of function as your code is in c# not unityscript (which is also long deprecated by now)
And then Yes, how old is that code you got there? The direct accesses to things like Component.animation, Component.renderer, Component.camera were deprecated years ago ^^
As the error already tells you rather use e.g. Component.GetComponent like e.g.
public class AnimationController : MonoBehaviour
{
// Reference this via the Inspector in Unity
// via drag and drop. Then you don't need GetComponent at all
[SerializeField] private Animation _animation;
private void Awake()
{
// or as fallback get it on runtime
if(!_animation) _animation = GetCompoenent<Animation>();
}
// Update is called once per frame
private void Update()
{
UpdateAnimations();
}
private void UpdateAnimations()
{
if (Input.GetKeyDown(KeyCode.W))
{
_animation.CrossFade("goup");
}
else if (Input.GetKeyDown(KeyCode.A))
{
_animation.CrossFade("goleft");
}
else if (Input.GetKeyDown(KeyCode.D))
{
_animation.CrossFade("goright");
}
else if (Input.GetKeyDown(KeyCode.S))
{
_animation.CrossFade("godown");
}
}
}
How have you defined "animation" in your code?
you could try adding animation reference in the top of the code:
private Animation animation;
and in your Start() or Awake() method, add:
// will add reference to the animation to be the Animation component
// in this GameObject
animation = GetComponent<Animation>();
I have a level in a game where when you get in a box collider, a portal opens, and when you leave it, it closes. Both portals need to open when I enter in box collider 1, and both need to close when i leave it. This also needs to happen when I enter in a box collider 2 of the second portal. I have a script for box collider 1 and I apply it to box collider 2. It checks if the player is in a collider. I have an animator bool which directly takes variable from box collider script to check in range. I use that bool for animation. However, that animator bool doesen't work for box collider 2. Variable for box collider works, but not animator bool. Is there a way to connect that second one, or do i need to make a new script for that box collider?
Box Collider Code:
public bool inRange;
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
inRange = true;
}
}
private void OnTriggerExit2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
inRange = false;
}
}
}
Portal Script Code:
public class Portal : MonoBehaviour {
private Animator anim;
private bool inPortalRange;
public GameObject portalBorder;
void Start ()
{
anim = GetComponent<Animator>();
}
void Update ()
{
OpenPortal();
UpdateAnimation();
}
private void UpdateAnimation()
{
anim.SetBool("inPortalRange", inPortalRange);
}
private void OpenPortal()
{
PortalBorder poborder = portalBorder.GetComponent<PortalBorder>();
inPortalRange = poborder.inRange;
}
}
A picture of a situation:
First of all you should not use GetComponent every frame. Either like the anim you should rather store it right away. Or you could simply make portalBorder of type PortalBorder then the according reference is set automatically when referencing it via the Inspector.
Then yes currently you are only updating one of the animators. In order to control them both you have to connect them somehow.
I would do something like this
public class Portal : MonoBehaviour
{
private Animator anim;
private bool inPortalRange;
// Public read-only access
public bool InPortalRange => inPortalRange;
// Reference each other via the Inspector in both portals
public Portal OtherPortal;
// Give this directly the according type so you don't need GetComponent at all
public PortalBorder portalBorder;
// I would recommend to do things always as early as possible
// Awake is executed before Start
private void Awake()
{
anim = GetComponent<Animator>();
}
private void Update ()
{
OpenPortal();
UpdateAnimation();
}
private void UpdateAnimation()
{
// Here now use the range of either this or the other portal
anim.SetBool("inPortalRange", InPortalRange || OtherPortal.inPortalRange );
}
private void OpenPortal()
{
inPortalRange = portalBorder.inRange;
}
}
However instead of making it a polling call in Update I would actually rather use an event driven approach:
public class PortalBorder : MonoBehaviour
{
public UnityEvent OnEnteredPortalRange;
public UnityEvent OnLeftPortalRange;
private void OnTriggerEnter2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
OnEnteredPortalRange.Invoke();
}
}
private void OnTriggerExit2D(Collider2D other)
{
if (other.CompareTag("Player"))
{
OnEnteredPortalRange.Invoke();
}
}
}
Now your script has to UnityEvent (just like the onClick of buttons) where you can add callbacks either via the inspector or using code
public class Portal : MonoBehaviour
{
public Animator anim;
private bool inPortalRange;
// Public read-only access
public bool InPortalRange => inPortalRange;
// Reference each other via the Inspector in both portals
public Portal OtherPortal;
// Give this directly the according type so you don't need GetComponent at all
public PortalBorder portalBorder;
// I would recommend to do things always as early as possible
// Awake is executed before Start
private void Awake()
{
anim = GetComponent<Animator>();
// Instead of checking a bool in Update simply
// wait until the according events get invoked
portalBorder.OnEnteredPortalRange.AddListener(EnablePortal);
portalBorder.OnLeftPortalRange.AddListener(DisablePortal);
}
private void OnDestroy()
{
// always make sure to remove callbacks when not needed anymore
// in roder to avoid NullReferenceExceptions
portalBorder.OnEnteredPortalRange.RemoveListener(EnablePortal);
portalBorder.OnLeftPortalRange.RemoveListener(DisablePortal);
}
public void EnablePortal()
{
anim.SetBool("inPortalRange", true);
OtherPortal.anim.SetBool("inPortalRange", true);
}
public void DisablePortal()
{
anim.SetBool("inPortalRange", false);
OtherPortal.anim.SetBool("inPortalRange", false);
}
}
I can't activate my Canvas with my Interactable(Coin) Script and the OnTriggerEnter(). I want to activate the Canvas(show my Text) when my Player collides with my Coin. The Script is in my Coin GameObject. My CoinCollider is on IsTrigger.
public string displayText;
public Text textView;
public GameObject Player;
public Canvas textCanvas;
// Start is called before the first frame update
void Start()
{
textCanvas.enabled = false;
}
// Update is called once per frame
void Update()
{
}
void onTriggerEnter(Collider2D other)
{
if (other.gameObject.tag == "Player")
{
textCanvas.enabled = true;
textView.text = displayText;
}
}
I tried making just the Text appear without a Canvas and watching Tutorials.
The problem is that the method name is "OnTriggerEnter2D" not "onTriggerEnter" for 2D collisions. This sho
I am attempting to play a sound when a user drags a 2D gameobject.
The gameobject will have to play many sounds, so I am programmatically creating Audio Sources and assigning clips through the inspector.
public class Card: Monobehavior, IDraggable {
public AudioClip tokenGrabClip;
public AudioClip tokenReleaseClip;
public AudioSource tokenGrab;
public AudioSource tokenRelease;
public AudioSource TokenGrab {
get{ return tokenGrab; }
}
public virtual void Start() {
tokenGrab = AddAudio (tokenGrabClip, false, false, 1f);
tokenRelease = AddAudio (tokenReleaseClip, false, false, 1f);
}
public virtual AudioSource AddAudio(AudioClip clip, bool isLoop, bool isPlayAwake, float vol) {
AudioSource newAudio = gameObject.AddComponent<AudioSource>();
newAudio.clip = clip;
newAudio.loop = isLoop;
newAudio.playOnAwake = isPlayAwake;
newAudio.volume = vol;
return newAudio;
}
}
This will create two audio sources for every gameobject of type Card in my game.
Now in my game manager, I simply try to play a sound...
void CheckDragStart(GameObject go, Draggable d) {
if (go.GetComponent<Card> () != null) {
print("check drag start");
go.GetComponent<Card> ().TokenGrab.Play ();
}
}
No sound is played, but I am able to to see my console with the "check drag start message".
Any idea what I could be doing wrong? I can see audio sources assigned to my game objects with my methods in the first code block, but my audio clips are not being assigned to them...
This can't be that go GameObject, GetComponent<Card>() or TokenGrab is null. If any of them is null, you will get the NullException error. I am ruling those out.
Looking at your code, these are the possible reasons why your audio is not playing. Ordered from very likely to least.
1.Your AudioClip is not assigned from the Editor.
Check that both of these variables are assigned fom the Editor.
public AudioClip tokenGrabClip;
public AudioClip tokenReleaseClip;
This must be done for each Card script that is attached to any GameObject in the scene.
You won't get any error if they are not assigned or null. It simply won't play.
2.Your Card script and the GameObject it is attached to is destroyed after Play() is called. Try to comment anywhere you have the Destroy function. Try it again. If problem is solved you have to fix that by moving your AudioSource to an empty GameObject that does not need to be destroyed.
I am just putting up my suggestion here. I see that you don't want to loop the clips. So why don't you try something like this?
public AudioClip tokenGrabClip;
public AudioClip tokenReleaseClip;
AudioSource audioSrc;
void Start () {
audioSrc = GetComponent<AudioSource> ();
}
public void PlayTokenGrabClip () {
audioSrc.PlayOneShot (tokenGrabClip);
}
public void PlayTokenReleaseClip () {
audioSrc.PlayOneShot (tokenReleaseClip);
}
Add an AudioSource component to your GameObject. Assign the audio files (mp3, wav) to tokenGranClip and tokenReleaseClip through the editor. Then call the functions PlayTokenGrabClip () and PlayTokenReleaseClip () to play the respective sounds as and when required.
The problem came from not updating my prefabs. I was assigning AudioClips in my C# script publicly, however, this change was not immediately reflected in my prefabs. Rather than having to update many prefabs, I reorganized how my resources load on startup:
I define my audio clips with Resources.Load(...) as AudioClip; in Awake() and create AudioSource Components in Start(). From this, I am able to add AudioClips to my AudioSources via C#.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Card : MonoBehaviour, IDraggable {
public bool counter;
private AudioClip tokenGrabClip;
private AudioClip tokenReleaseClip;
private AudioSource tokenGrab;
private AudioSource tokenRelease;
public AudioSource TokenGrab {
get{ return tokenGrab; }
}
public AudioSource TokenRelease {
get{ return tokenRelease; }
}
public virtual void Start() {
tokenGrab = AddAudio (tokenGrabClip, false, false, 0.5f);
tokenRelease = AddAudio (tokenReleaseClip, false, false, 0.5f);
}
public virtual void Awake () {
tokenGrabClip = Resources.Load ("Audio/tokenGrab") as AudioClip;
tokenReleaseClip = Resources.Load ("Audio/tokenRelease") as AudioClip;
}
public virtual AudioSource AddAudio(AudioClip clip, bool isLoop, bool isPlayAwake, float vol) {
AudioSource newAudio = gameObject.AddComponent<AudioSource> () as AudioSource;
newAudio.clip = clip;
newAudio.loop = isLoop;
newAudio.playOnAwake = isPlayAwake;
newAudio.volume = vol;
return newAudio;
}
}
Game starts, the music begins to play, but it's too annoying and want to mute or just make it quieter. Like games, there's setting menu, which I thought it would be good to be in next scene, and there I want to put slider.
But I got errors.
Script:
using UnityEngine;
using System.Collections;
public class Music : MonoBehaviour
{
void Awake()
{
DontDestroyOnLoad(transform.gameObject);
}
public AudioClip[] soundtrack;
// Use this for initialization
void Start()
{
if (!GetComponent<AudioSource>().playOnAwake)
{
GetComponent<AudioSource>().clip = soundtrack[Random.Range(0, soundtrack.Length)];
GetComponent<AudioSource>().Play();
}
}
// Update is called once per frame
void Update()
{
if (!GetComponent<AudioSource>().isPlaying)
{
GetComponent<AudioSource>().clip = soundtrack[Random.Range(0, soundtrack.Length)];
GetComponent<AudioSource>().Play();
}
}
}
You use AudioSource.volume to change the volume. When you create a Slider, you can get the value of the slider with Slider.value. So, take Slider.value and assign it to AudioSource.volume.
To create s Slider, go to GameObject->UI->Slider. Make sure that Min Value is 0 and Max Value is 1. Also make sure that Whole Numbers check box is NOT checked. Drag the Slider to the volume Slider slot in this script from the Editor.
Note:
If you are going to use a component more than once, cache it to a global variable instead of doing GetComponent<AudioSource>() multiple times or using it in the Update() function.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class Music : MonoBehaviour
{
public AudioClip[] soundtrack;
public Slider volumeSlider;
AudioSource audioSource;
void Awake()
{
DontDestroyOnLoad(transform.gameObject);
}
// Use this for initialization
void Start()
{
audioSource = GetComponent<AudioSource>();
if (!audioSource.playOnAwake)
{
audioSource.clip = soundtrack[Random.Range(0, soundtrack.Length)];
audioSource.Play();
}
}
// Update is called once per frame
void Update()
{
if (!audioSource.isPlaying)
{
audioSource.clip = soundtrack[Random.Range(0, soundtrack.Length)];
audioSource.Play();
}
}
void OnEnable()
{
//Register Slider Events
volumeSlider.onValueChanged.AddListener(delegate { changeVolume(volumeSlider.value); });
}
//Called when Slider is moved
void changeVolume(float sliderValue)
{
audioSource.volume = sliderValue;
}
void OnDisable()
{
//Un-Register Slider Events
volumeSlider.onValueChanged.RemoveAllListeners();
}
}
You can learn more about Unity's UI here.