I'm trying to make a mobile sidescroller and I want the player to be able to jump higher if the jump UI button is held down, I could not find any toturials on youtube for mobile and I'm reletively new to scripting so I tried to do it by myself but it did not work properly, the only toturials I can find are for pc and I can't implement them correctly for mobile because they require Input.getbuttondown and inputs like that impossible for mobile, this is my current script, the jump ui button has event trigger
public void Jump()
{
if (isGrounded())
{
jumping = true;
animator.SetBool("NowJumping", true);
SoundManager.PlaySound("PlayerJump");
rb.velocity = new Vector2(rb.velocity.x, jumpPower);
if (jumping)
{
rb.velocity = new Vector2(rb.velocity.x, rb.velocity.y * 0.5f);
}
}
public void StopJump()
{
jumping = false;
}
the jump is always boosted by the if (jumping) velocity boost,
I'm out of ideas on how to put this feature in my game, anyone have any ideas how to fix this? Thank you very much in advance
I would start coroutine when jumping starts. Like 0.5 secs long. After coroutine ends, it makes the jumping false and stops jumping even if you keep pushing the button down. I am in my phone, so i can't test this. I suppose while you are pressing the button down, it always makes the jumping true because of the way you designed your code. So to make it work, you can make jumping true when key is pressed the first time (not holding down). Then in OnButtonHeldDown() you can make if (jumping) {bla bla}. This way when coroutine ends it makes jumping false and jumping would not be true again while pressing button. Player needs to release and press again to make jumping true. And like you wrote, it cannot release button and press again the trick the code, because only when it is grounded it can jump. I hope i managed to explain my reasoning.
Also you can make the button uninteractible after 0.5 secs and make in interactible again after the character is grounded.
For coroutine usage, you can check here.
https://docs.unity3d.com/Manual/Coroutines.html
Set jumping to false using OnPointerUp. You can read how to use it here
https://docs.unity3d.com/2018.3/Documentation/ScriptReference/UI.Selectable.OnPointerUp.html
Related
I am working on a 2D video game project but I have a somewhat strange error in the character's attack. I've been using Unity for a short time...
When I press the attack button, an animation is played and a boolean variable is set to true. When the attack animation ends, it has an event in place that calls a function to change the boolean variable back to false.
Main script added to player gameobject (MonoBehaviour):
void Update(){
if (Input.GetKey(script_buttons.button_attack))
{
gun_attacking = false;
player_animator.Play("gun_attack");
}
}
Event that is called when the weapon attack animation ends:
void foot_gun_attack()
{
attack_script.gun_attacking = false;
}
It works fine, but if I quickly press the attack button, there are times when the variable never goes to false, and the game goes crazy.
Is it unreliable to use events in the animations themselves? why does it fail and not change the boolean variable to false again?
I have partially fixed it by adding a State machine behavior script to the animation, and in said script, right in the OnStateExit function I change the variable to false. This works and the attack never misses no matter how fast you press the button, the problem? which forces me to have both at once, the animation event and the state machine behavior script. If I remove the event the vairable never goes false, if I remove the state machine behavior the variable does go false but fails every once in a while.
Script on state machine behavior:
override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
attack_script.gun_attacking = false;
}
The only way it won't fail is to set the variable to false in both places, which I think is crazy and shouldn't be normal behavior. The animation event should suffice and work fine, but why isn't it working correctly? I wouldn't like to have to limit button presses or add Timeouts, or would that be the only way?
Maybe it's my mistake or Unity problem, does anyone know what's going on?
The reason may be that the animation never ends and goes to another state
The first way is that
When You can call the function you want when the animation starts, but in the coroutine, it waits for the animation time and then returns the bool to false.
or continue with your own method, but check and change this configuration in the transitions before and after that animation.
Especially try these 2 checkboxes
I want to create jumping animation from 2 sprites and.
The animation can be illustrated like this
When his position is at the highest value, he changes state. Then keep that state until he falls off and changes to idle state.
I have done the research, watched tutorials on youtube, and I found something called blend tree. Then I went to the Unity documentation website and my mind was spinning around and around, I just couldn't understand it. And is there any way to know when his position is at the highest value? or any solution to animate him? And when to use blend tree
And also, a link to the tutorial
I would work with velocity conditions.
Let's say you start with an idle animation as default.
Then you make a transition from animation "idle" to animation "jumping" with the conditions IsGrounded = false to check if you're at the ground and velocityY > 0 to check if you're jumping or not.
Then do another transition from "jumping" to "landing" with the conditions IsGrounded = false and VelocityY < 0 so it checks if you're falling and will change the animation to the landing animation.
I am new to C# and Unity and I'm trying to figure out how to make an animation for an object in unity play when I press a key but I can only make the animation play once, and then it is broken and doesn't work. (I am trying to make an FPS game)
The code I have right now looks like this:
void Start()
{
gameObject.GetComponent<Animator>().enabled = false;
}
// Update is called once per frame
void Update()
{
if (Input.GetButtonDown("Fire1"))
{
Shoot();
gameObject.GetComponent<Animator>().enabled = true;
}
}
When I press run and left click, the animation triggers and does as it is supposed to but when I try to do it again, the animation doesn't work. Can anybody help me change this code so that the animation will work and play every time the button is pressed?
I am assuming your animation is non-looping as if it was looping it would already play back into itself when it is over.
One quick note I would have with your code is do not use GetComponent in an Update function as it is quite costly. An easy way to get an animation state to reset is to enable and disable it, however I am assuming you want to have more animations than shooting. You would want to look into what is called an Animation Tree or a Blend Tree and add States to your animation. Examples of states would be an Idle, Walk, Run, Shoot, Crouch, etc. I would consider researching Animation Trees and Blend Trees to get a full animation cycle in.
Once you get a State machine working, I would have the enter go to an Idle state, then either set a transition Bool or directly switch the animation in code.
// when you serialize a private field, it will appear in
// the inspector so you can drag in the reference in the editor
[SerializeField] private Animator anim = null;
private void Start()
{
anim.enabled = false;
}
private void Update
{
if(Input.GetButtonDown("Fire1")
{
Shoot();
if(!anim.enabled)
anim.enabled;
else
anim.Play("AnimationStateName", -1, 0f);
}
}
I have not tested the code, but I believe this would work with your setup. I would still strongly advise to not do this and look into Trees. After implementing the tree, instead of calling using the enabled, just use the line anim.Play("AnimationStateName", -1, 0f) or you can do anim.SetBool(isAttacking, true) if you set your state to transition from Idle/Run/Walk/etc. to Attacking when the isAttacking bool is set to true.
I found a video that might help you out. I do not want to post a full explanation to animation states and blend trees, just point you in the right direction to a better approach.
The following code locks the cursor only when I left click my mouse after pressing Escape Key. Can anyone suggest me a way to overcome this problem?
public class lockCursor : MonoBehaviour
{
public bool locked = true;
// Start is called before the first frame update
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Escape))
{
if (locked == false)
{
Debug.Log("locked");
Cursor.lockState = CursorLockMode.Locked;
locked = true;
}
else
{
Debug.Log("Unlocked");
Cursor.lockState = CursorLockMode.None;
locked = false;
}
}
}
}
As said in the API for Cursor.lockState
In the Editor the cursor is automatically reset when escape is pressed, or on switching applications.
Due to escape having a special role itself within the Unity Editor the GameView loses focus when pressing it.
There is not really a (trivial) way around this since it would require to intercept they keypress before the Unity Editor itself gets the chance to handle that escape press. (Which would always happen before it is passed on to the player -> your code.)
What you can do however would be simply use a different KeyCode only for the editor and escape only in a build like e.g.
#if UNITY_EDITOR
if(Input.GetKeyDown(KeyCode.E))
#else
if(Input.GetKeyDown(KeyCode.Escape))
#endif
{
...
You can replace the E with any other KeyCode you wish to use to "simulate the escape key" only within the Unity Editor itself. (Also see Platform dependent compilation)
As derHugo mentioned in his comment, your issue lies in the API for Cursor.lockState where it says:
"In the Editor the cursor is automatically reset when escape is
pressed, or on switching applications. In the Standalone Player you
have full control over the mouse cursor, but switching applications
still resets the cursor."
When you go to press Escape, it removes you from the application/Game Window. This is why it'll appear like your cursor is no longer locked. This is also why it goes into it's locked state as soon as you click back into the game. The same thing can be demonstrated by using your code, starting the game and then switching into another window on another monitor. Then move your mouse back over to the screen where the Game Window is. It'll appear as though it is no longer in a locked state... that is until you click in the game and it recognizes the cursor again.
To solve your problem, I would recommend using any key other than KeyCode.Escape. Maybe KeyCode.Space like the API shows.
Also, to further demonstrate the issue here, once you switch the code to use KeyCode.Space, press Space to lock the cursor and then try pressing Escape. Again you'll see that it appears to be unlocked until you press the Left Mouse Button in the Game Window again. This is because the Game thinks that you are no longer in the Game Window once you press Escape.
Hope this helps!
I am a total beginner at Unity3d. I have some background in android programming, but no C# experience whatsoever. The first thing I am trying to do is to create a clone of flappy bird game, called flappy plane, according to this tutorial
http://anwell.me/articles/unity3d-flappy-bird/
The problem is, when I tried to write a script that allows player to move (player.cs) with the code
using UnityEngine;
using System.Collections;
public class player: MonoBehaviour {
public Vector2 jumpForce = new Vector2(0,300);
public Vector2 jumpForce2 = new Vector2(0,-300);
// Use this for initialization
// Update is called once per frame
void Update () {
if (Input.GetKeyUp("space")){
Rigidbody2D.velocity = Vector2.zero;
Rigidbody2D.AddForce(jumpForce);
}
}
}
I get an error "An Object reference is required to access non-static member 'UnityEngine.Rigidbody2D.velocity'". I have googled that and it is suggested to access Rigidbody2d with GetComponent().velocity,
so I changed
Rigidbody2D.velocity = Vector2.zero;
Rigidbody2D.AddForce(jumpForce);
with
GetComponent<Rigidbody2D>().velocity = Vector2.zero;
GetComponent<Rigidbody2D>().AddForce(jumpForce);
The error is gone and I am able to add the script to the object, still I don`t get the desired action - after I hit play the object turns invisible and just falls down, does not react to spacebar button. What am I doing wrong?
Thanks for the answer.
It's possible that you're not adding enough force to have the object move upwards.
There's technically nothing wrong with your code. (Although you do have somethings mixed up in your question). The problem is in the fact that you're not adding ANY force upwards every single frame.
Essentially, at the moment, your player object is in free-fall the instant you hit the play button, and you're adding a minuscule force to the player only on the frames that the space bar is pressed.
To solve this, here's what you should be doing
Add an upward force to counter-act the force of gravity every frame. You can do this in two ways.
a. Set the rigidbody's velocity.y to 0 BEFORE detecting the space bar (this is really a hacky way, but it'll suffice and doesn't need any more code)
b. Add an upward force to the player which will nullify the effect of gravity. Just use F = mg to get the value of force you'd need to add.
You could, alternatively set the isKinematic property to true by default on the Player's rigidbody, set it to false on pressing the space bar, and back to true after a few frames (5 - 6 frames)
make sure your player object and the ground both have BoxCollider2D colliders to keep above ground.
you could keep a reference stored for the rigidBody like Rigidbody2D myRigidbody;
then in start put myRigidbody = GetComponent<Rigidbody2D>(); then you would use like myRigidbody.AddForce(jumpForce); your jumpForce2 though is shooting your player downward you should not need it in a jump as the physics and gravity will apply with the rigidbody.
incase your input is not set up in the project settings try to fire the jump with
Input.GetKeyDown(KeyCode.Space);