• 0

[C#] Door animation script in Unity. IF statement issue.


Question

Hi guys,

 

Hoping someone here can help me with C# and Unity.

 

I'm working on a project and trying to animate a door I created in 3DS max. I've attached a script to a switch in the scene and press it. It isn't acting as I would expect.

 

Instead of playing the open animation, it just plays the close animation every time I interact with the switch.
Adding the Debug lines, shows that "First" is passed twice for every interaction and "Closed" and "Opened" are passed once each. I'm struggling to see why this is and hoping a fresh pair of eyes could spot the issue and suggest a solution.

using UnityEngine;
using System.Collections;

public class DoorSwitch : MonoBehaviour 
{
	public GameObject door;
	public GameObject button;
	public bool isDoorOpen = false;

	private GameObject player;

	// Use this for initialization
	void Awake () 
	{
		player = GameObject.FindGameObjectWithTag(Tags.player);
	}

	void OnTriggerStay (Collider other) 
	{
		if(other.gameObject == player)
			if(Input.GetButtonDown("Switch"))
				DoorToggle();
	}

	void DoorToggle()
	{
		Debug.Log("First");
		if(isDoorOpen == true)
		{
			isDoorOpen = false;
			door.animation.Play("Closing");
			button.renderer.material.color = Color.red;
			Debug.Log("Closed");
		}
		else if(isDoorOpen == false)
		{
			isDoorOpen = true;
			door.animation.Play("Opening");
			button.renderer.material.color = Color.green;
			Debug.Log("Opened");
		}
	}
}

16 answers to this question

Recommended Posts

  • 0

If you just want to use a last used timer you only need a few lines:

 

        static readonly TimeSpan DoorDelay = TimeSpan.FromSeconds(3);
        DateTime lastDoorToggle = DateTime.MinValue;

        public void DoorToggle()
        {
            DateTime now = DateTime.Now;
            if (now.Subtract(lastDoorToggle) < DoorDelay)
                return;

            lastDoorToggle = now;

            Debug.Log("Door animation runs");
            // rest of door logic
        }
This way you have no timers running that you don't need.
  • 0

Looks fine to me.  The only thing I can think of is that the switch is being triggered twice.  You could add in a timeout that if the switch is hit within 3 seconds (or something) of the last hit you ignore it.

  • 0
  On 13/04/2015 at 18:22, Seabizkit said:

yeah looks fine but my guess is that your creating a new DoorSwitch each time... i would need to understand how this is consumed to ensure that there is only one instance and the same instance of the DoorSwitch

Yea, was thinking that after too.  That maybe you are binding two cases in case of on/off but without seeing how you bind, it's hard to say for sure.

  • 0

I've added these three screenshots.

 

The first shows the switch and the inspector, I've looked at all items in the hierarchy to make sure I haven't added the script to another object.

The second is the imported animations, not sure if there's any settings there that I should tweak. The same goes for the third screenshot of the door model in the hierarchy.
 

post-438852-0-67093800-1428949795.png

post-438852-0-43131100-1428949853.png

post-438852-0-48379000-1428949880.png

  • 0
  On 13/04/2015 at 18:19, firey said:

Looks fine to me.  The only thing I can think of is that the switch is being triggered twice.  You could add in a timeout that if the switch is hit within 3 seconds (or something) of the last hit you ignore it.

 

Still finding my way around C# and Unity, any pointers to how I could make a timeout for the switch? I've tried reading up about Coroutines and IEnumerator, but I'm not sure how to implement it within the script.

  • 0
  On 13/04/2015 at 19:06, DaveGreen93 said:

Still finding my way around C# and Unity, any pointers to how I could make a timeout for the switch? I've tried reading up about Coroutines and IEnumerator, but I'm not sure how to implement it within the script.

I'm not entirely sure how unity works.  You could do it a couple ways, the simplest approach is to do something like this:

 

bool ignoreSwitch = false;
timer tmrIgnore;

protected void initialize() 
{
   tmrIgnore = new timer();
   tmrIgnore.Interval = 3000;
   tmrIgnore.Tick += new tmrIgnore_tick();
   tmrIgnore.Enabled = false;
}

protected void tmrIgnore_tick() 
{
    ignoreSwitch = false;
    tmrIgnore.Enabled = false;
}

protected void toggleDoor()
{
   if (!ignoreSwitch) {
      //run your code
      ignoreSwitch = true;
      tmrIgnore.Enabled = true;
   }
}

It's a really rough concept and by no means the best.  I mean ideally unity would give you ticks that you could just keep track of (ticks since last call).  However it should give you an idea.

  • 0
  On 13/04/2015 at 19:29, firey said:

I'm not entirely sure how unity works.  You could do it a couple ways, the simplest approach is to do something like this:

 

bool ignoreSwitch = false;
timer tmrIgnore;

protected void initialize() 
{
   tmrIgnore = new timer();
   tmrIgnore.Interval = 3000;
   tmrIgnore.Tick += new tmrIgnore_tick();
   tmrIgnore.Enabled = false;
}

protected void tmrIgnore_tick() 
{
    ignoreSwitch = false;
    tmrIgnore.Enabled = false;
}

protected void toggleDoor()
{
   if (!ignoreSwitch) {
      //run your code
      ignoreSwitch = true;
      tmrIgnore.Enabled = true;
   }
}

It's a really rough concept and by no means the best.  I mean ideally unity would give you ticks that you could just keep track of (ticks since last call).  However it should give you an idea.

 

Hmmm, timer isn't included in Unity. Guess I'll have to research Coroutines more. Hopefully my lecturer can get back to me asap.

 

Thank you for your time and ideas firey.

  • 0
  On 13/04/2015 at 19:54, DaveGreen93 said:

Hmmm, timer isn't included in Unity. Guess I'll have to research Coroutines more. Hopefully my lecturer can get back to me asap.

 

Thank you for your time and ideas firey.

No problem, sorry I couldn't offer more assistance.  

  • 0
  On 13/04/2015 at 19:06, DaveGreen93 said:

Still finding my way around C# and Unity, any pointers to how I could make a timeout for the switch? I've tried reading up about Coroutines and IEnumerator, but I'm not sure how to implement it within the script.

 

I think a hint to the solution is in the documentation of your event:

 

  Quote

 

OnTriggerStay is called once per frame for every Collider other that is touching the trigger

 

keyword: Once per frame. You could try to add yield after the Call to your DoorToggle(), but I have not read up on how they work With events.  Or add a timestamp that cancels the Logic if the event is triggered within x milliseconds. 

  • 0
  On 14/04/2015 at 14:58, Eric said:

If you just want to use a last used timer you only need a few lines:

 

        static readonly TimeSpan DoorDelay = TimeSpan.FromSeconds(3);
        DateTime lastDoorToggle = DateTime.MinValue;

        public void DoorToggle()
        {
            DateTime now = DateTime.Now;
            if (now.Subtract(lastDoorToggle) < DoorDelay)
                return;

            lastDoorToggle = now;

            Debug.Log("Door animation runs");
            // rest of door logic
        }
This way you have no timers running that you don't need.

 

 

Excellent, thank you Eric! After adding using System; it worked flawlessly. My lecturer was useless in helping.

 

Also, thank you everyone else for your suggestions.

  • 0

Hi DaveGreen93

 

Not that I care about unity but i do care about my understanding of c# logic.

 

Could you explain why this works and your original does not, as to me its in either one of two states..."open" or "closed".

 

If there is an instance of DoorSwitch per a door then i don't understand why the original logic doesn't work.

 

Could you explain how a timer fixes the issue.

 

Thanks

  • 0
  On 14/04/2015 at 17:09, Seabizkit said:

Hi DaveGreen93

 

Not that I care about unity but i do care about my understanding of c# logic.

 

Could you explain why this works and your original does not, as to me its in either one of two states..."open" or "closed".

 

If there is an instance of DoorSwitch

per a door then i don't understand why the original logic doesn't work.

 

Could you explain how a timer fixes the issue.

 

Thanks

Behavior scripts in Unity are trigged for as long as the input is active so even a quick click on a switch could result in the event firing multiple times. A time delay ensures that the door routine doesn't toggle open/closed repeatedly for one click. I used a static 3s delay in my example but I suppose you could probably retrieve the animation time from the engine and use that instead.

  • 0
  On 14/04/2015 at 23:00, Eric said:

Behavior scripts in Unity are trigged for as long as the input is active so even a quick click on a switch could result in the event firing multiple times. A time delay ensures that the door routine doesn't toggle open/closed repeatedly for one click. I used a static 3s delay in my example but I suppose you could probably retrieve the animation time from the engine and use that instead.

 

Thank you!!! now it kinda makes sense its odd tho,

 

Is all game programming like this?

 

Wouldn't this consume large amounts of pointless CPU cycles?

 

Is it considered normal to have events fire like this?

 

how long is your animation for the door?

 

have you scripted it to that as its opening and its half way (assume 3 secs) and you click it again, does it start closing from the correct animation point.

 

I would assume you would need to code extra code for this... so that its starts the animation from the correct point?

 

PS door looks cool

 

PS re-read it. OK i see the click itself can be fired multiple time while holding it down... now i see why the delay was introduced its not for the animation but for time between allowed clicks...?

  • 0

Well, it's DaveGreen's code, but yes to most of that. The "switch" just looks like a switch. In reality the engine is just detecting the player is colliding with the switch and generating a signal while they're touching. Using the time delay I posted will still cause it to generate the door event as long as you're touching the switch it just doesn't respond to it except every three seconds. It's similar to keyboard "debouncing."

Games do waste CPU cycles. The trick is to get it to a minimum so it runs smoothly. That's why I suggested the timestamp instead of a timer. The timer runs in the background. :)

  • 0
  On 15/04/2015 at 13:43, Eric said:

Well, it's DaveGreen's code, but yes to most of that. The "switch" just looks like a switch. In reality the engine is just detecting the player is colliding with the switch and generating a signal while they're touching. Using the time delay I posted will still cause it to generate the door event as long as you're touching the switch it just doesn't respond to it except every three seconds. It's similar to keyboard "debouncing."

Games do waste CPU cycles. The trick is to get it to a minimum so it runs smoothly. That's why I suggested the timestamp instead of a timer. The timer runs in the background. :)

 

Thanks Eric

This topic is now closed to further replies.
  • Posts

    • Become a PDF Expert on your Mac — One-time purchase now at 42% off by Steven Parker Today's highlighted deal comes via our Apps + Software section of the Neowin Deals store, where for only a limited time you can save 42% on PDF Expert One-Time Purchase. PDFs remain the best way to transmit documents, but editing them isn't possible with standard Mac software. PDF Expert changes that, allowing you to edit PDF text, images, links, and outlines quickly and easily. Typo in a contract? Easy fix. Need to rework a complete section of a document? No problem. PDF Expert provides a series of essential functions that will transform the way you work with documents on your Mac. It recognizes text and OCR, makes edits, and fills out forms. And with the “Enhance” feature powered by AI, it will fix distortions, remove shadows and improve contrast so that even difficult-to-read documents look great. EDIT Change the text. Easily fix typos, update numbers, or add entire paragraphs Insert images. Update logos in a contract or add a new graph to a report Add links. Enrich your PDFs by linking to other pages or external websites ANNOTATE Highlight the important. Make the most valuable content stand out at a glance Comment on PDFs. Add text to PDFs, insert pop-up notes & write your thoughts in the margins Add stamps. Review documents with our set of stamps or create custom stamps for any workflow ORGANIZE Merge PDFs. Combine multiple files into one PDF document Manage pages. Add, delete, rearrange, or rotate PDF pages with ease Split PDFs. Extract pages from PDFs & save them as separate files CONVERT Convert to PDF. Turn JPG, PNG, Word, PPT, and Excel to PDF PDF to Word. Convert PDFs into editable Word documents PDF to image. Turn PDFs into JPG or PNG images PDF to Excel. Convert PDFs into Excel spreadsheets PDF to PPT. Save PDFs as PowerPoint presentations PDF to text. Convert PDFs into editable TXT files FILL OUT Fill out PDF forms. Easily fill out PDF forms by just clicking on them Sign documents. Add your signature to a PDF in a few clicks. Let customers sign documents with handy one-time signatures Redact PDFs. Blackout or erase confidential information from your documents RECOGNIZE TEXT OCR text in PDF. Recognize the text, so you can search, highlight & copy it Enhance scans. Fix distortions, remove shadows & improve contrast Crop & split pages. Split double-page scans into separate pages & remove undesired margins Good to know: Length of access: Lifetime Redemption deadline: redeem your code within 30 days of purchase Access options: Mac Max number of device(s): Unlimited usage on personal macOS devices Version: PDF Expert 3 for Mac (macOS) Updates: Get continuous support and bug fixes. Additional new features may come at an extra cost. PDF Expert One-Time Purchase normally costs $139.99, but you can pick it up for just $79.97 for a limited time, that represents a saving of $60 (42% off). For a full description, specs, and license info, click the link below. Get PDF Expert for just $79.97, or learn more Although priced in U.S. dollars, this deal is available for digital purchase worldwide. We post these because we earn commission on each sale so as not to rely solely on advertising, which many of our readers block. It all helps toward paying staff reporters, servers and hosting costs. Other ways to support Neowin Whitelist Neowin by not blocking our ads Create a free member account to see fewer ads Make a donation to support our day to day running costs Subscribe to Neowin - for $14 a year, or $28 a year for an ad-free experience Disclosure: Neowin benefits from revenue of each sale made through our branded deals site powered by StackCommerce.
    • It all went down hill after he retired from the ring, nothing really to do with him being a trumpster (as are most wrestlers). Hulk in general was a bad person after his retirement.
    • Debian switches to 64-bit time completely to avoid Y2K38 disaster by Usama Jawad Some of you may remember the Y2K problem, where the world expected airplanes to fall from the sky as soon as we reached the year 2000, primarily because many software applications at that time typically just used the final two digits of each year to store calendar year data, which meant that the year 2000 was indistinguishable from the year 1900. Fortunately, we were able to avoid the 2K problem, thanks to the tireless efforts of many software vendors and engineers. Now, we are a few years away from a similar issue, and it looks like the Linux distro Debian wants to solve that problem right now in its own operating system. Basically, older 32-bit architectures will face the Y2K38 problem in the year 2038. This is because the signed representation of Unix datetime values will overflow the 32-bit space, which would cause bugs in associated software. Debian is a pretty old distro with its first release dating back to 1993, so the maintainers say that a lot of sensitive computing is still happening on 32-bit architecture. Although there are still roughly 13 years to go before we reach 2038, developers want to proactively tackle the problem rather than having to scramble at the last minute like with Y2K, according to The Register. Another name for Y2K38 is the Unix Epochalypse, since it impacts systems that store datetime values in the Unix format within a signed 32-bit space. On January 19, 2038, 03:14:07 UTC, this space will overflow. As such, Debian maintainers will use 64-bit time_t formats even on 32-bit architectures starting with the release of Debian 13 "Trixie". This is not a small change, as maintainers found the use of the time_t variable in random places across 6,429 packages. The maintainers went on to say that: This may be a breaking change for some applications, so it is important to test your program's response to the time_t variable switch by leveraging the Debian wiki. Interestingly, Y2K38 may also impact certain older Windows programs and out-of-support Windows operating systems.
    • I hope they programed its eyes to turn red when it becomes evil, that is an important feature for any AI representation.
    • Microsoft gives Copilot visual appearance with real-time expressions and emotions by Taras Buria Several months ago, during its 50th anniversary event, Microsoft teased a visual upgrade for Copilot (then called "Copilot Avatar") that would give the chatbot a visual character with expressions, reactions, and emotions. Now, users in the US, UK, and Canada can try Copilot Appearance, "a new, visual way to chat." Conversational mode has been available in Copilot for a while, but it lacked any visual cues or non-verbal communications. All users see on their screens is some abstract animation. With Copilot Appearance, Microsoft is improving voice conversations with real-time visual expressions. Sadly, Copilot Appearance is not a Clippy 2.0. In its current form, it is an abstract blob with a face that can morph into different shapes, express emotions, nod in agreement, etc. The concept is similar to what xAI offers with Grok AI companions that cost $300 per month, but Microsoft's approach is much more toned down (and you cannot undress it). On the official Copilot Labs website, Microsoft describes Copilot Appearance as "an experiment to incorporate a more visual, engaging experience into Copilot." Copilot Appearance is rolling out to a limited set of users in just three countries as Microsoft takes a cautious approach to a more personified AI. If you have a lucky ticket, you can try Copilot Appearance by launching Voice Mode (click the microphone button in the composer) and toggling the feature in Voice Mode settings. Microsoft says that the initial release is experimental, and it is working on refining the experience.
  • Recent Achievements

    • Week One Done
      CyberCeps666 earned a badge
      Week One Done
    • Very Popular
      d4l3d earned a badge
      Very Popular
    • Dedicated
      Stephen Leibowitz earned a badge
      Dedicated
    • Dedicated
      Snake Doc earned a badge
      Dedicated
    • One Month Later
      Philsl earned a badge
      One Month Later
  • Popular Contributors

    1. 1
      +primortal
      627
    2. 2
      ATLien_0
      240
    3. 3
      Xenon
      163
    4. 4
      +FloatingFatMan
      124
    5. 5
      neufuse
      123
  • Tell a friend

    Love Neowin? Tell a friend!