Why doesn't my character attack while moving diagonally? - c#

I've followed some simple tutorials on Udemy and Youtube, and I created a player controller that involves walking and attacking. I cannot seem to figure out why I can't attack while holding down 2 directional inputs. The attack animation plays when I am moving up and right, but not down/right, down/left, or up/left.
Here is the code I am using
void Update()
{
//Movement
theRB.velocity = new Vector2(Input.GetAxisRaw("Horizontal"), (Input.GetAxisRaw("Vertical"))) * moveSpeed;
myAnim.SetFloat("moveX", theRB.velocity.x);
myAnim.SetFloat("moveY", theRB.velocity.y);
//Attack
if (Input.GetKeyDown(KeyCode.Space))
{
Attack();
}
void Attack()
{
myAnim.SetTrigger("Attack");
}
}
I understand that the Attack() method has no effect yet besides the animation, but I cannot get the animation to play while moving diagonally. Any help would be appreciated.

Ok, let me explain you bitwise
that you can't run 2 animations at a time when using Unity animator. I think that you might be using kinda this
Instead of beating from any state. I mean see it will be on IDLE by default and it will only attack if the character is on IDLE animation. So to prevent this you can use
What it will do is it will set the player even if it's walking. You must set back transition to IDLE if not walking and back transition to walking if it's walking. If you are doing this mistake I hope so you got your answer.

Related

Why the object is never rotating towards the target?

void Update()
{
if (pickUp)
{
if(Roll.hasStopped)
{
animator.SetTrigger("Walk Forward");
Vector3 targetDirection = (target.position - transform.position).normalized;
target.rotation = Quaternion.LookRotation(targetDirection);
transform.rotation = Quaternion.RotateTowards(transform.rotation, target.rotation, Time.deltaTime);
}
}
}
The transform is the player and he is start walking forward "Walk Forward", but he never rotate towards the target. he keep moving straight walking forward.
The "Walk Forward" is a trigger parameter i'm using in my animator controller on a transition to a state with HumanoidWalk animation.
The question is why the transform is not rotating towards the target and keep walking straight forward instead ?
Maybe you're overriding the rotations with the animator.SetTrigger? Idk too much of animation, but It seems odd to me that animator.SetTrigger is called in every frame and after that there's no flag raised to stop calling it over and over.
From what I've seen in the docs, this trigger gets called after a certain event (i.e press a key) but not in every frame. Hope it helps :)

Transition FPS Camera Animation from Idle to Walking?

So, I recently learned how to animate certain objects, but I don't know how the code works.
I learned the animator tab, where idle camera animation will transition from walking if I am holding my movement keys. I searched tutorials on youtube and google, but all I can find are animations found on models, not actually on the camera.
If I used that logic on a camera, nothing actually happens, and I don't know what to write.
I've set a bool, which is labeled "WalkingForward", because I have different animations on different movements.
When it is true, the forward walk animation will play, and if false, it turns back to idle animation.
The only thing I can't figure out is a code that will detect the "Horizontal" and "Vertical" movements to start playing the animation.
Here is the link of my animator controller tab https://imgur.com/a/euM9yFl , and I would really appreciate if someone has an idea.
You can handle/detect movement in the Update() method for a GameObject, then get the Animator for the Camera and set the Animator parameters.
See Unit Animation Parameters Docs for more info, but the general idea is something like this:
// Update method attached to wherever you want to detect movement
void Update()
{
// isMovingHorizontally and iMovingVertically are not defined here
// They could either be based off the speed/momentum of the GameObject
// Or the input from the player
var isMovingHorizontally = isMovingHorizontally();
var isMovingVertically = isMovingVertically();
animator.SetBool("MovingHorizontally", fire);
animator.SetBool("MovingVertically", fire);
}

How can I make sure the sound only plays once and doesent bug?

So in my character movement script I'm trying to play the jump audio I have when my character jumps. This works just fine but a problem I have is that:
In my game when I hit a enemy object my character movement stops and a menu comes up. The issue here is sometimes I hit a enemy object whilst still in the air. This causes my jump sound to bug out and constantly replay really quickly creating a really awful noise since when i hit the object my character stops moving in the air.
Just to be clear the issue isnt with hitting the actual enemy the problem is that I have the jump sound to play when I jump and since I die on top of the enemy I assume the jump sounds keep repeating itself because I never actually exit the jump because on death all character movement stops so I'm still stuck on top of the hurdle so the jump never really ends and then a menu comes onto the screen.
my current code for the jumping is:
if (controller.isGrounded)
{
// Jumping for pc
verticalVelocity = -gravity * Time.deltaTime;
if (Input.GetKeyDown(KeyCode.Space))
{
verticalVelocity = jumpForce;
animator.SetBool("is_in_air", true);
jump.Play();
}
}
What would i have to do in here in order to only make the jump.Play(); only play once and not keep repeating itself and making that horrible noise when I die ontop of an enemy object?
Edit: I guess a potential fix could be to mute just the jump sound clip or audiosource once the death menu pops up.

Creating an endless spinner in Unity

I want a gameobject spinning around its y-axis. This spinner should have a initial movement direction and when colliding with something, it should change its direction.
I created a little picture to show what I mean, but I want the behaviour for a 3D game.
So I just started with the rotation of the spinner,
public class Spinner : MonoBehaviour
{
[SerializeField]
private float movementSpeed; // speed when moving
[SerializeField]
private float rotationSpeed; // speed when rotating
private Rigidbody rigid;
private Vector3 movementDirection; // the direction the spinner is moving
private void Start()
{
rigid = GetComponent<Rigidbody>();
}
private void FixedUpdate()
{
transform.Rotate(0, rotationSpeed, 0); // rotate the spinner around its y-axis
}
private void OnCollisionEnter(Collision col)
{
// set new direction
}
}
How can I move the spinner, that it moves along a direction and whenever it collides with something, it changes its direction. It should never stop moving or rotating.
I would like to point out a few things:
The Unity Physics Engine will make collisions to absorb part of the force which moves your spinner, so unless you keep adding "artificial" forces to the spinner it will eventually stop.
The "air friction" in your scene will also reduce the force of your
spinner, so it will slow it down. You should add a material to the
spinner which has 0 Dynamic Friction
Based on the comment you left in #reymoss' answer, you may consider
to add the bouncy material to the walls, and not to the spinning
GameObject.
To sum up, the issue here is if you want a GameObject to bounce against a wall using the Physics Engine, the object will eventually stop, because some of the forces will be absorbed in each collision. That means you will need to keep adding external forces every time a collision takes place, to keep it moving endlessly.
Something you can try is,
1- Add a bouncy material to the walls and remove the dynamic friction of your spinner. In the following link you can learn about this:
https://docs.unity3d.com/Manual/class-PhysicMaterial.html
2- Add to the Spinner a Collider, so when it detects a collision with a wall (you can tag the walls as so for example) add an additional force to the spinner in the direction it is already moving, so it will compensate the energy lost during the collision.
void OnTriggerExit(Collider other) {
if(other.tag == "wall") {
rigidbody.AddForce(rigidbody.velocity.normalized * Time.deltaTime * forceAmount);
}
}
The idea is to let the Engine decide the direction of the Spinner after the collision with the wall, and as soon as the GameObject leaves the trigger, you add an additional force in the current direction.
Then you can play with the Bounciness of the wall's material and with the forceAmount, until your spinner moves as you have in mind.
Note: Since you will have 2 materials, one in the walls and another in the spinner, maybe playing with the Friction Combine and Bounce Combine you will be able to avoid the force lost during collisions, so you will not need to add the external force I mention in the second step. However I have never tried this.
Let me know if it works. I can't try myself the solution until I arrive home.
If you give the object an initial velocity, attach a collider, create and assign a Physics Material 2D to the collider (to apply bounciness), and attach Colliders to the walls, you can have it bounce around with minimal code.
private void Start()
{
rigid = GetComponent<Rigidbody>();
rigid.velocity = new Vector3(2f, 3f, 1f) // initialize velocity here
}

How to stop a sphere from moving by itself after restarting its position?

I am on my third day of learning Unity and are currently doing the roll-a-ball tutorial. I am trying to add a restart button, that teleports the ball back to the start-position/origin. It all works good, but the ball will keep moving after I restart, but I want it to stay in a spot and not move by itself.
What I mean is that if I'm moving left at max speed and press 'R' to restart, then it will keep moving left fast for some time, but what I want to achieve is that the ball would not keep moving by itself after I restart it's position (perhaps it's speed is just decreasing so slow that it's unnoticeable, in which case I'd want it to slow down faster).
Here's my code that I just tried out and "hoped" would work, but doesn't. I think that the problem I have here is that a new axisHorizontal/axisVertical variable value is assigned again the next frame, the value being taken from Input.GetAxis, which from what I have heard is not possible to change.
That means that a movementForce bigger than 0/0/0 and AddForce will be activated again the next frame.
using UnityEngine;
using System.Collections;
public class PlayerScript : MonoBehaviour {
public float movementSpeed = 7f;
private Rigidbody rigidSphere;
void Start() {
rigidSphere = GetComponent<Rigidbody>();
}
void FixedUpdate() {
float axisHorizontal = Input.GetAxis("Horizontal");
float axisVertical = Input.GetAxis("Vertical");
Vector3 movementForce = new Vector3(axisHorizontal, 0.0f, axisVertical);
rigidSphere.AddForce(movementForce * movementSpeed);
if (Input.GetKeyDown(KeyCode.R)) {
transform.position = new Vector3(0, 0, 0);
rigidSphere.AddForce(0, 0, 0);
axisHorizontal = 0;
axisVertical = 0;
}
}
}
I tried googling on how to change the value that is taken from GetAxis, but others claim it's impossible to do so. So I have really no idea how to make it not keep moving forever...
And I also got a 'bonus' question that has arised during those two days that I have been learning Unity, but they are not worth a seperate question, perhaps if they have been already answered before (I've been unable to find any documentation that'd help me on it), then just give me a link on where I could find the answer to my problem.
The question is that how do I make the ball stop moving after some time after I press a button (W/A/S/D, the default values for positive/negative buttons in Input Manager)? For example, I press 'W' just for a second, but the ball will keep moving forward forever and will never stop.
What I want to achieve is after I for example press 'W' for a second, after a few seconds the ball will completely stop, it just seems that the value from GetAxis never goes back to 0. I tried to google about it, and I think it's something to do with Gravity in the Input Manager - I tried changing it, but the ball will still keep moving forever, the only thing I noticed did change was the speed of the ball.
I'd be really grateful if someone could help me with these problems.
I am trying to add a restart button, that teleports the ball back to
the start-position/origin. It all works good, but the ball will keep
moving after I restart, but I want it to stay in a spot and not move
by itself.
I see that you tried to solve this by using rigidSphere.AddForce(0, 0, 0);. This will only add 0,0,0 to the existing force the ball is moving at. The solution to this is to set the Rigidbody velocity to 0.
Replace rigidSphere.AddForce(0, 0, 0); with rigidSphere.velocity = Vector3.zero;
Even when you do this, Input.GetAxis value increases and decreases over time before reaching 0. So, on the next frame, the ball might still be moving due to this.
To stop this, also replace Input.GetAxis with Input.GetAxisRaw.
Input.GetAxisRaw will immidiately return to 0 when the key is released.
What I want to achieve is after I for example press 'W' for a second,
after a few seconds the ball will completely stop, it just seems that
the value from GetAxis never goes back to 0.
Since the ball is rolling, you need to increase the angular drag of the ball. This will make the ball stop rolling after releasing the key. The angular drag is on the Rigidbody attached to the ball. Also increase the drag if that's not enough.

Categories

Resources