Unity New Input System and Animations - unity3d

I am creating a basic 2D fighter game and am trying to replace what was the old input system with the new input system. Because of this the old systems update would wait for buttons and then call appropriate functions when they were pressed. Movement was actually the easiest part, simply rigging a 1D Vector and then grabbing the float to use with movement, awesome. However the difficulty is in pressing keys to change things in the game. For example, I have an input 's' which should lead to the method Crouch(). This method changes the animation running and alters the hitbox to be shorter and tell the attack to use a smaller hitbox as well. A Stand() method is called on release of 's' to return everything to the way it is. I have my Player Input object set to 'Invoke Unity Events' which leads to the corresponding method needed. The problem is that even though these events are set to be push and release they are read as a toggle effect instead of press and release triggers(respectively). This does the same thing with my attack function because it forces the animation to play twice, one for pressing and one for releasing. Is there a fix for this or is this currently a bug? Edit: Here are some images to clarify and the code used to reflect everything happening associated with the Attack functionality. Let me know if anything else should be needed
public void Attack(){
anim.SetTrigger("attack");
StartCoroutine(wait());
}
IEnumerator wait(){
if(!isCrouched){
yield return new WaitForSeconds(1.3f);
SHitBox.enabled = true;
yield return new WaitForSeconds(.5f);
SHitBox.enabled = false;
}
if(isCrouched){
yield return new WaitForSeconds(1.3f);
CHitBox.enabled = true;
yield return new WaitForSeconds(.5f);
CHitBox.enabled = false;
}
}
Binding
Action

Think I figured it out. At least for the purposes of this specific thread. The answer was it was not my code. There is what I am going to call a bug in the new Unity Input System. Specifically there were three lines of code all simultaneously being hooked which caused three calls on my method. The fix was commenting out two lines of code. Here's the thread where this is solved, coincidentally found on GitHub help pages, heres the link:
https://github.com/Unity-Technologies/InputSystem/issues/959
the issue is listed as close but its still a problem for me, lol...
The only issue left is that the behavior of selecting the type of button press that I want to use is still acting funky. Mainly the inputs are still simply firing without listening to the type of input I want. I am basically just going to start searching through unity code to find where these choices have impact. If there are no comments/answers in 8 hours I'll accept my own answer because this has technically been answered, it just leads to another question.

Related

Unity 3D: what is the correct way to detect that the collision has already been processed for another collision participant?

I have a class CollisionHandler which has the OnCollisionEnter method. Each collideable entity in the game has CollisionHandler as a component. So, when 2 objects collide the OnCollisionEnter method is called twice and it's ok because the damage and other things are processed as a result of touching object "B" by object "A" and vice versa.
In addition, each collision creates a flash effect and plays a sound of impact and of course, these effects are also played twice for each collision. Although it wouldn't be imperceptible to the player it doesn't seem to be correct anyway. In order to prevent it, I came up with the following solution: I save the current frame number in another collision participant so it will know that these effects have been played already by the first one.
private void OnCollisionEnter(Collision collision)
{
// Calculate the damage caused by `this.gameObject` to `collision.gameObject`.
// ...
// Play an impact sound and show a visual effect.
if (thisObject.CollisionFrameId != Time.frameCount)
{
otherObject.CollisionFrameId = Time.frameCount;
// play sound
// show hit effect
}
}
Although it works I'm not sure (I'm a novice in Unity) that it's the best practice and if so please suggest other possible solutions.
Note that I didn't ask "Why is OnCollisionEnter getting called twice?". I know why it happens. My question is about the other, though it does mention the name of the same function it still doesn't asks the same.
You could do a GetComponent on the other object with one of your scripts (or the same script) and set the RecentCollisionObject to the current script or gameObject (and maybe a given time frame just for additional safety (if only one triggers it, but not the other for some reason)).
On each collision you check if RecentCollisionObject is the other object (and if no more than ~0.01 seconds has passed). If true, you know that particular collision must already have been processed by the other object just now, so reset all values from that other object and do nothing else. So the next collision which occurs, no matter how soon, will do this cycle anew and work as expected.
This way you let only the first to trigger the collide code execute your code (like a sound). The point is that both collision events are ran in the same frame, so no matter which triggers first, you can prevent the second from running.
You can use the Unity Tag System, you tag action to occur when colliding with that specific tagged object.
As example:
internal void OnTriggerEnter(Collider other) {
if (other.gameObject.tag == "Oject Tag") {
this.GetComponent<AudioSource> ().PlayOneShot (objectTagSoundClip);
}
Just need a audio to play placed in game object.
Maybe you have 2 Colliders. If so you could check if boxcollider for example is colliding only. You could also try on Collision leave. Hope it helps.

Method for Back button not working when Time.TimeScale=0

I have written below code for Back button event.
void Update()
{
if (Input.GetKey(KeyCode.Escape))
{
SceneManager.LoadScene("PreviousLevel");
}
}
In almost all cases this is fine. But I have found a small issue. When the user pauses the game, this doesn't work. When the user pauses the game, I do Time.timeScale=0. Initially, I gave a thought of modifying pause method and instead of doing Time.timeScale=0, use a bool variable and modify other pause logic accordingly. But then I also realized that I have over 14 co-routines whose logic is heavily dependent on Time.timeScale and modifying those will take a lot of time. They are heavily dependent on time.timeScale.
I wanted to know, is there any other method where I can write back button logic and which is not dependent on Time.timeScale.
It should work, input polling in Unity is not dependent on the time scale.
Try by inserting a Debug.Log inside the condition, and you should see it in the console.
Watch out if you put the if inside FixedUpdate and not Update: in that case it won't work since FixedUpdate is completely skipped when time scale is 0.
However, if you want a "dirty" trick, you can slow the timescale to a very low number, without using 0, i.e.: 10e-8. But use it with a lot of care, since it can lead to unwanted behaviour.
Input is dependent on time scale: GetButton() works normally but GetAxis() works inconsistently, for example getting mouse movement with GetAxis() works as expected, but getting Horizontal and Vertical returns 0 when timeScale is 0. You can get around this by using Input.GetAxisRaw().
It should also be noted that any axis also counts as a button, so you can also use GetButton() on those but the return value will be bool instead of float.

Difference btw. sendmessage and setting Value

What is the difference between those two methods? Why should i prefer one?
1)
GameObject.FindGameObjectWithTag("").GetComponent<Rocket>().active = true;
2)
GameObject.FindGameObjectWithTag("").GetComponent<Rocket>().SendMessage("setActive");
thanks!
Sending a message searches through all the components of the gameObject and invokes any function that has the same name as the message. Not a 100% sure but Im sure this uses reflection which is generally considered slow.
SetActive() or the active variable set the gameObject as active or not. If its not active it wont render in the scene and vice versa.
First of all it seems there are several inconsistencies with your code above:
1) Components (and MonoBehavior) don't have an active property (active belongs to GameObject), so the first line of code shouldn't compile. In addition the most recente version of unity don't have active anymore, it's substitued with activeSelf and activeInHierarchy.
And btw, both activeSelf and activeInHierarchy are read only, so you can't assing directly a value to them. For changing their value use SetActive method.
2)
The second line of code shouldn't work either (unless Unity does some magic behind the scenes) because SetActive methods belong to GameObject and not to your Rocket Component.
Now, I suppose your question was the difference between:
gameObject.SetActive(true);
and
gameObject.SendMessage("SetActive",true);
The result is the same, but in the second way Unity3D will use reflection to find the proper method to be called, if any. Reflection has an heavy impact on performance, so I suggest you to avoid it as much as possible.

Is it really wrong to use Input.GetKey() on FixedUpdate?

We know there's a "rule" that Input functions shouldn't be used inside the FixedUpdate(); Input.GetKeyDown() may not work if we do so, but is it really wrong to use Input.GetKey()?
Let's say we want to fire something when pressing and holding a key at some rate that is not dependent on hardware performance. I don't want to create a logic to control this using delta time or writing key detection code in Update and firing code in FixedUpdate.
Doesn't make sense to just do everything inside FixedUpdate? What can happen - we may lose some key pressed events, the ones that we didn't want anyway, to keep our desired rate.
But what if one single key event happens, can we lose it? Is there a reset after Update, so we won't see it on FixedUpdate?
From the GetKeyDown docs:
You need to call this function from the Update function, since the
state gets reset each frame
So yes, the Input state is reset each frame meaning hardware will have an effect depending on how frequently Update fires between FixedUpdate.
There really isn't an easy way to avoid creating a copy of the Input that is used by FixedUpdate, though I would suggest reevaluating your logic to move things in to Update.
Update:
Regarding Rutter's comment below. I just noticed the OP was asking about GetKey(), what I wrote about GetKeyDown() remains true for GetKey() though the documentation doesn't explicitly say so.
This can be verified by going in to the Time Manager and changing the FixedUpdate rate to some long interval like 1 second. Then do something like:
void FixedUpdate() {
if(Input.GetKey(KeyCode.D)){
Debug.Log("D-Key Down");
} else {
Debug.Log("No key down");
}
}
If you press and release 'D' between the 1 second fixed frames you will only see "No Key Down".
In my experience, Update occurs at frame-time, unlike Fixed Update which can occur multiple times per-frame. In addition, The physics of objects are actually updated before FixedUpdate() is called, which means there could be a delay based on the complexity of the scene.
I believe that Input is actually broadcasted per-frame, so when the FixedUpdate() is behind and needs to catch up by firing multiple times, the Input check will fail.
Additional Resources:
http://answers.unity3d.com/questions/10993/whats-the-difference-between-update-and-fixedupdat.html

gtk.fixed layout laid out events?

I have a gtk.Fixed. I move components inside it around using:
myFixed.move( myEventBox, new_x, new_y )
What event do I listen for to know when myEventBox has been rendered at its new position?
Do I connect to the fixed or the eventbox?
MORE INFO:
I need this information so I know when it is safe to queue a video under the eventbox... if I do it too soon (e.g. right after calling myFixed.move) I can see the glitch. Currently getting around this with a gobject.idle_add.
To be honest, I am not aware of any such event. The object should move immediately and redraw the screen, but I don't think any signal is emitted when that happens.
The PyGTK documentation is very comprehensive, and it will list all of the functions and events of every object in the library. In searching (through both the gtk.Container (for fixed) and gtk.Widget (for fixed and eventbox) signal lists, I can't find any such event. The closest thing is an "add" signal in gtk.Container, but I don't think that's what you're looking for.
If the object is not moving, please post your code, because there is probably a subtle error.
If the object is moving just fine and you just want the event/signal, you may have to simulate it yourself. Write the function you want to be called as soon as the object is moved in a function (def) inside "__ init __", and then call that function in code in the line right after "myFixed.move".