I have a UI Image GameObject and i want to make it so that if you hover over it for a second it zooms but if at any point the cursor leaves the GameObject stays the same size. The way i wanted to do it was to check for first Pointer enter with OnPointerEnter and after a second elapses to check again if the cursor is on the Image but i had no luck with trying to find a way of checking if mouse is over the Image. Another thing i tried to find was if there is any way to delay OnPointerEnter by one second but most of the stuff i found made it delayed but if i moved my cursor away from the Image it would still zoom after a second.
You can set flag when PointerEtner and PointerExit, so that you can get the cursor isHovered by that flag.
public bool isHovered = false;
public void DoWhenHover()
{
isHovered = true;
StartCoroutine(DelayZoom());
}
IEnumerator DelayZoom()
{
yield return new WaitForSeconds(1);
print("Zoom the image");
}
public void DoWhenExit()
{
isHovered = false;
StartCoroutine(DelayRecover());
}
IEnumerator DelayRecover()
{
yield return new WaitForSeconds(1);
print("Reset the image");
}
Related
I have an InputAction callback where I am recording the position where the player clicks the screen, but only if the click is not over a UI element. Here's my code
private void OnPress(InputAction.CallbackContext context)
{
if (!EventSystem.current.IsPointerOverGameObject())
{
this.pressPosition = Mouse.current.position.ReadValue();
}
}
This has been working correctly. However, I recently updated my version of Unity, and now I'm getting this warning every time I click somewhere in my game:
Calling IsPointerOverGameObject() from within event processing (such as from InputAction callbacks)
will not work as expected; it will query UI state from the last frame
According to the changelog, this warning was added with an update to the input system.
Is there a way to figure out whether the mouse was over the UI when the player clicks the screen without getting this warning?
how I solved it was by moving just that piece of logic to an Unity's Update function:
private void Update()
{
if (Mouse.current.leftButton.wasPressedThisFrame)
{
if (EventSystem.current.IsPointerOverGameObject(PointerInputModule.kMouseLeftId))
// was pressed on GUI
else
// was pressed outside GUI
}
}
You can still keep using the inputsystem, i.e. when cancelled:
private void OnPress(InputAction.CallbackContext context)
{
if (context.canceled)
// Left mouse is no longer pressed. You can do something within the input system notification.
}
private bool pressControl = false;
private void Update()
{
if (Mouse.current.leftButton.wasPressedThisFrame)
pressControl =!EventSystem.current.IsPointerOverGameObject(PointerInputModule.kMouseLeftId);
}
void selector(InputAction.CallbackContext context)
{
if (!pressControl) return;
pressControl = false;
Vector3 position = new Vector3(mausePositionEvent.ReadValue<Vector2>().x, mausePositionEvent.ReadValue<Vector2>().y, 0);
Ray ray = Camera.main.ScreenPointToRay(position);
RaycastHit hit;
if (!Physics.Raycast(ray, out hit)) return;
}
I'm working on a laser that fires for a set amount of time before switching off.
I am using WaitForSeconds calling the fire function, waiting for x seconds and then turning it off.
I can see it working by turning the colliders and sprites on and off in the Unity menus, but they never physically appear in the game; whereas without the code they do appear.
void Start()
{
StartCoroutine(LaserTimer());
}
void LaserFire()
{
beamCollider.enabled = true;
beamSprite.enabled = true;
}
void StopFire()
{
beamCollider.enabled = false;
beamSprite.enabled = false;
}
IEnumerator LaserTimer()
{
LaserFire();
yield return new WaitForSeconds(5);
StopFire();
yield return new WaitForSeconds(5);
}
I have several stat bars, attached to objects, that shorten in length over time. If the PC collides with the object, the stat bar should steadily increase in length instead.
Instead, the bar lengthens to its fullest extent, and doesn't begin to shorten again until the PC interacts with another stat bar object; at which point the bar goes back to the length it had been previously.
This is the code for the progression of the bars:
void Update() {
if (contact) {
Increase();
Debug.Log("increasing");
} else if (contact == false) {
Decrease();
Debug.Log("decreasing");
}
}
void Decrease() {
if (filled > 0) {
filled -= 0.006f;
timerBar.fillAmount = filled / maxTime;
}
}
void Increase() {
if (filled < maxTime) {
timerBar.fillAmount = (filled += 0.006f);
}
}
In a separate script, I am keeping the conditions for the definitions of "contact".
void OnCollisionEnter2D(Collision2D collision) {
if (collision.gameObject.tag == "Player") {
barProg.contact = true;
Debug.Log("is touching");
}
}
void OnCollisionExit2D(Collision2D collision) {
if (collision.gameObject.tag == "Player") {
barProg.contact = false;
Debug.Log("is not touching");
}
}
Here are the images regarding the script attachments and colliders:
"yellowBar (progBar)" etc. are referring to the scripts attached to the canvas images of the statbars. So the little yellow depleting line (a statbar) is "yellowBar", and it references the script attached to the individual stat bar (progBar).
Shown below is an example of what I'm talking about. I refill the blue bar, at which point it stays the same until I go to refill the yellow bar, at which point the blue bar goes back to the amount it had been when I refilled it.
your going to want something like this, this is pseudo so bear with me....
bool healing=false;
public void OnTriggerEnter2D(Collisider2D col)
{
if(col.tag=="Player")
{
healing = true;
}
}
public void OnTriggerExit2D(Collisider2D col)
{
if(col.tag=="Player")
{
healing = false;
}
}
public void Update()
{
if(healing)
{
if(filled<maxTime)
{
timerBar.fillAmount += 0.006f;
}
}
}
bnwhose health your increasing, so each one needs the script.
you PC must be tagged "Player" to catch the collision.
your objects will need colliders, i assume they already have them.
and either the object or pc, will need a rigidbody. it seem you have most of this already. the reason this works is beacuae of the boolean. it sets it true when you enter the trigger and false when you leave it. so its only tru for that item while your touching that item, then inupdate while its true, we increase the healthbar.
putting this script on each of your objects directly will keep them from conflicting with each other, or updating the rong one.
good luck!
I have several suggestions to hopefully get you on the right track. This script should be attached the objects that fill up the status bars. you need to write a separate script to actually adjust the status bars based on the fillpercentage, but I'll leave that to you. This script is ONLY responsible for tracking how full, not displaying anything. This is good practice to separate your logic from your UI, since you can change one without affecting the other.
Also, you should avoid using "magic numbers" in your code. Make variables instead. see https://en.wikipedia.org/wiki/Magic_number_(programming)
Furthermore, you can switch between increasing and decreasing using a bool, rather than calls to separate methods. This keeps the logic in the same place and makes changing it in the future easier.
public class ColoredObject : Monobehaviour {
//bool to switch increasing and decreasing
bool increasing = false;
//can set this value in inspector to adjust speed it fills
//can even have different fill speeds for each color
public float fillSpeed;
//stores how full the bar is
float percentageFull = 100;
//if player contacts, start increasing
void OnCollisionEnter2D(Collision2D collision) {
if (collision.gameObject.tag == "Player") {
increasing = true;
}
}
//if player exits, start decreasing
void OnCollisionExit2D(Collision2D collision) {
if (collision.gameObject.tag == "Player") {
increasing = false;
}
}
void Update () {
UpdateFill()
}
public void UpdateFill() {
if (increasing) {
//fill based on time passed since last frame
percentageFull += fillSpeed * Time.deltatime;
}
else {
//empty based on time passed since last frame
percentageFull -= fillSpeed * Time.deltatime;
}
// keep it between 0 and 100%
percentageFull = Mathf.Clamp(percentageFull, 0f, 100f);
}
}
Let me know how it goes, and I can try to help you fine-tune it if this wasn't exactly what you wanted.
EDIT: if you want different increasing and decreasing speed just add another variable, and replace fillSpeed in the decreasing section.
I am calling ChangeVideo() from an invoke method:
InvokeRepeating ("ChangeVideo", 1, TimeToChangeImage);
public void ChangeVideo()
{
public string[] VedioPaths ={"aa","bb"}
System.Random random1 = new System.Random();
PathNO1 = random1.Next (VedioPaths.Length);
ConfirmPath1 = VedioPaths[PathNO1];
Handheld.PlayFullScreenMovie (ConfirmPath1,Color.black,FullScreenMovieControlMode.CancelOnInput);
}
I need to play the next video soon after the other finishes. How can I do that? I tried many ways but every time I build I get an error.
I have a string array from which I randomly select a video; once the first video finishes the next one should start playing. I tried using the invoke method but it is giving me an error.
If you want to load videos in a coroutine:
void Start()
{
StartCoroutine(LoadVideos());
}
IEnumerator LoadVideos()
{
//first vid
Handheld.PlayFullScreenMovie("vid1.mp4", Color.black, FullScreenMovieControlMode.CancelOnInput);
yield return new WaitForEndOfFrame();
yield return new WaitForEndOfFrame();
//second vid
Handheld.PlayFullScreenMovie("vid2.mp4", Color.black, FullScreenMovieControlMode.CancelOnInput);
yield return new WaitForEndOfFrame();
yield return new WaitForEndOfFrame();
}
Note that two lines of yield return new WaitForEndOfFrame(); is absolutely required for this method to work. The reason is unknown to me but it won't work otherwise.
Take a look closer to the documentation : https://docs.unity3d.com/ScriptReference/Handheld.PlayFullScreenMovie.html
Calling this function will pause Unity during movie playback. When playback finishes Unity will resume
Meaning that, if you want to play 2 videos one after the other, you just have to do :
Handheld.PlayFullScreenMovie (path1,Color.black,FullScreenMovieControlMode.CancelOnInput);
Handheld.PlayFullScreenMovie (path2,Color.black,FullScreenMovieControlMode.CancelOnInput);
Waiting between the two calls may be required though.
There is a very easy way for the lastest VideoPlayer to detect the loop point even if it‘s not looping.
public VideoPlayer videoPlayer;
public VideoClip[] videos;
public VideoClip theVideo;
public static int index;
bool isPlaying = true;
void Start()
{
index = 0;
videoPlayer = gameObject.GetComponent<VideoPlayer>();
videoPlayer.loopPointReached += CheckOver;
}
void CheckOver(UnityEngine.Video.VideoPlayer vp)
{
print("Video Is Over");
index += 1;
if (index >= videos.Length)
{
index = 0;
}
theVideo = videos[index];
videoPlayer.clip = theVideo;
videoPlayer.Play();
isPlaying = true;
}
is there a simple UnityScript code to hide and unhide a cube
or any other gameobjects for a particular time ?
//make the object invisible
renderer.enabled = false;
// make the object visible
renderer.enabled = true;
// toggle object's visibility each second
function Update () {
// Find out whether current second is odd or even
var seconds : int = Time.time;
// Enable renderer accordingly
renderer.enabled = oddeven;
To show/hide a game object, rather than using render.enabled property, you should use
// Deactivates the game object.
gameObject.SetActive (false);
More details can be found here.
To call this function periodically, as theodox said, startCoroutine is your friend.
You want to hide the object, fire off a coroutine that waits for N seconds, and then unhide.
This is C#, the conversion to Javascript should be simple but I don't think JS uses startCoroutine (This page in the docs explains the difference between the C# and Javascript versions).
public bool Hide = false;
void Update()
{
if (Hide && renderer.enabled) {
renderer.enabled = false;
Hide = false;
StartCoroutine("WaitUnhide");
}
}
IEnumerator WaitUnhide()
{
yield return (new WaitForSeconds(2));
renderer.enabled = true;
}
In this version you would set the 'hide' variable from some other code to start the hiding. Hide && renderer.enabled means you can't kick off a new hide until the old one completes - that's not the only way to do it but it avoids having multiple hide/unhides overlapping.
To make it loop forever:
void Start()
{
StartCoroutine("HideUnhide");
}
IEnumerator HideUnhide()
{
while (true) {
yield return (new WaitForSeconds(2));
renderer.enabled = true;
yield return (new WaitForSeconds(2));
renderer.enabled = false;
}
}