This is part of my code.
if (Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.LeftArrow))
{
_turnDirection = 1.0f;
}
else if (Input.GetKey(KeyCode.D) || Input.GetKey(KeyCode.RightArrow))
{
_turnDirection = -1.0f;
}
I have a weird problem: The player will turn left but wont turn right. IDk why.
if you want the full code i can provide that: https://pastebin.com/CJ0wAVi0
Your issue is with your FixedUpdate. Instead of only rotating when _turnDirection is greater than zero, try rotating whenever it is not equal to zero since _turnDirection can be negative.
Related
I am trying to create a procedural gun controller, but I can't find why my gun behaves so weird when I change the fire mod to automatic. To understand this better, I will give an example: when I try to shoot by pressing the "Mouse0" key, on semi auto mod it works fine, it behaves like I want it to (the bolt kicks back when I shoot, the front barrel kicks back - I animate them with code instead of frame animations from Unity or a 3rd party soft like Blender), but..., when I change to automatic, the problem is not that I get errors, The animations of the moving pieces don't work as they should and are not triggered correctly.
I tried to use different methods for shooting(using the WaitForSeconds() and WaitForSecondsRealtime() while using coroutines). It didn't work. I tried using the time function with scaled and unscaled time in the update function. I still got the same results.
What should I do to?
This is the shoot function untill now:
void GunFireManagement()
{
if (fireType == fireMethod.single)
{
foreach (BlowBack anim in animations)
{
if (Input.GetKeyDown(KeyCode.Mouse0))
{
gunSoundClone = Instantiate(gunShootSound, this.transform.position, Quaternion.identity) as GameObject;
anim.piece.transform.position = anim.kickbackState.transform.position;
}
if (anim.piece.transform.position != anim.initialPosition.transform.position)
{
anim.piece.transform.position = Vector3.Lerp(anim.piece.transform.position, anim.initialPosition.transform.position, anim.speed);
}
Destroy(gunSoundClone, 0.5f);
}
}
if (fireType == fireMethod.auto)
{
foreach (BlowBack anim in animations)
{
if (Input.GetKey(KeyCode.Mouse0) && Time.time - lastFired > 1f/autoFireRate)
{
lastFired = Time.time;
gunSoundClone = Instantiate(gunShootSound, this.transform.position, Quaternion.identity) as GameObject;
anim.piece.transform.position = anim.kickbackState.transform.position;
}
if (anim.piece.transform.position != anim.initialPosition.transform.position)
{
anim.piece.transform.position = Vector3.Lerp(anim.piece.transform.position, anim.initialPosition.transform.position, anim.speed);
}
Destroy(gunSoundClone, 0.5f);
}
}
}
The issue is how you are using Vector3.Lerp. The first two arguments you pass to the method are supposed to be the start and end positions of the animation, and the third one, t, is supposed to be the progress of the animation from the start towards the end, as a value between 0 and 1.
You can calculate the value of t by dividing the time since the shot started with the duration of the animation. For example if the length of the animation is 2 seconds, and the short started 1 second ago, then t should be 0.5.
if(isFiring)
{
float timeSinceShotStart = Time.deltatime - lastFired;
// t = s / v
float animationDuration = 1f / anim.speed;
UpdateBlockBackAnimationState(timeSinceShotStart / animationDuration);
}
}
private void SetBlowBackAnimationState(float progress01)
{
foreach(BlowBack anim in animations)
{
Vector3 initialPosition = anim.initialPosition.transform.position;
Vector3 finalPosition = anim.finalPosition.transform.position;
anim.piece.transform.position = Vector3.Lerp(initialPosition, finalPosition, progress01);
}
}
I recommend you try to split up your code into smaller methods that are easier to understand. You are trying to do so many things in one generic "GunFireManagement" method that it becomes pretty difficult to keep track of all the different pieces :)
I also recommend considering using a tweening framework such as DOTween to make it easier to animate things over time.
I am new to Unity and so far enjoy my journey. Right now I have accomplished my knife constant rotation within [-30;30] degrees range. However, after the user presses any key, my knife should be moving fast in the direction it currently faces.
How can I achieve the following behavior? I tried addForce, changing velocity, but no results... Perhaps it is even impossible to do?
Here my knife is facing the left angle and I would like to it to just move in that direction really fast. No fancy effects :)
Here is the initial knife position.
Here is source code:
public void HandleRotation()
{
if (transform.rotation.z >= 0.3f)
{
right = false;
}
else if (transform.rotation.z <= -0.3f)
{
right = true;
}
if (right)
{
begin = begin + 0.05f;
}
else
{
begin = begin - 0.05f;
}
var tiltAroundZ = begin * tiltAngle;
var target = Quaternion.Euler (0, 0, tiltAroundZ);
transform.rotation = Quaternion.Slerp(transform.rotation, target, Time.deltaTime * smooth);
}
Translate(transform.forward())? If forward is the wrong axis, you could try up or right.
There should also be a version of the Translate method that includes a space parameter, in this case you'd use Space.Self instead of Space.World, which it currently is defaulting to.
I've created an arm with a custom pivot in Unity which is essentially supposed to point wherever the mouse is pointing, regardless of the orientation of the player. Now, this arm looks weird when pointed to the side opposite the one it was drawn at, so I use SpriteRenderer.flipY = true to flip the sprite and make it look normal. I also have a weapon at the end of the arm, which is mostly fine as well. Now the problem is that I have a "FirePoint" at the end of the barrel of the weapon, and when the sprite gets flipped the position of it doesn't change, which affects particles and shooting position. Essentially, all that has to happen is that the Y position of the FirePoint needs to become negative, but Unity seems to think that I want the position change to be global, whereas I just want it to be local so that it can work with whatever rotation the arm is at. I've attempted this:
if (rotZ > 40 || rotZ < -40) {
rend.flipY = true;
firePoint.position = new Vector3(firePoint.position.x, firePoint.position.y * -1, firePoint.position.z);
} else {
rend.flipY = false;
firePoint.position = new Vector3(firePoint.position.x, firePoint.position.y * -1, firePoint.position.z);
}
But this works on a global basis rather than the local one that I need. Any help would be much appreciated, and I hope that I've provided enough information for this to reach a conclusive result. Please notify me should you need anything more. Thank you in advance, and have a nice day!
You can use RotateAround() to get desired behaviour instead of flipping stuff around. Here is sample code:
public class ExampleClass : MonoBehaviour
{
public Transform pivotTransform; // need to assign in inspector
void Update()
{
transform.RotateAround(pivotTransform.position, Vector3.up, 20 * Time.deltaTime);
}
}
Though I begin with a very nicely, oriented globe:
After a lot of manual intervention and spinning, the globe may look like this:
Obviously, I should be implementing some sort of restoration function that will restore the globe on a certain axis to a point.
I have naively created the following code:
if(transform.parent.rotation.eulerAngles.y != 0)
{
goalRotation.eulerAngles = new Vector3(transform.parent.rotation.eulerAngles.x, transform.parent.rotation.eulerAngles.y, 0);
transform.parent.rotation = Quaternion.Slerp(transform.parent.rotation, goalRotation, Time.deltaTime);
}
However, this obviously does not work. It is definitely rotating the globe, but it's not moving as expected...
Is there anyone with more experience with Slerp or something similar that can rotate my globe to a 0 point?
As always, any help or advice is much appreciated.
EDIT: In case I wasn't clear before, I am looking to achieve something like this: https://gfycat.com/PeacefulJubilantCottontail (This is my solution to the problem). I did try to use other solutions here, but I guess there was a misunderstanding because they did not work.
While, the following naive code sorta works, I still feel there is a better way to do it...
if (fix && (lastControlled + 5f < Time.time))
{
goalRotation.eulerAngles = new Vector3(90, transform.parent.rotation.eulerAngles.y, 0);
transform.parent.rotation = Quaternion.Slerp(transform.parent.rotation, goalRotation, Time.deltaTime);
}
if (fix && (transform.parent.rotation.eulerAngles.x == 90) && (transform.parent.rotation.eulerAngles.z == 0))
{
fix = false;
}
The only real remaining issue I am having is that Slerp works towards the desired point, but it does not take the quickest path. Any further help would be appreciated.
Is this what you are trying to do?
quaternion defaultRotation = transform.parent.rotation;
bool returnToDefault = false;
void Update()
{
if(returnToDefault)
{
Vector 3 rot = new Vector 3 (transform.parent.rotation.x, Quaternion.Slerp(transform.parent.rotation, defaultRotation, Time.deltaTime).Euler.y, transorm.parent.rotation.y);
transform.parent.EulerAngles = rot;
}
}
And just change the variable returnToDefault to true whenever you want it to go back. Otherwise, you are constantly fighting your code, which as your wrote it is always rotating it back to default.
I have the following Bird, I want when the player touch a point on a screen to apply velocity on the Bird and move it to that point.
So I wrote the following:
if (Input.touches.Length > 0)
{
foreach(Touch touch in Input.touches ){
Vector2 pos = touch.deltaPosition;
rigidbody2D.velocity = pos;
}
}
The problem is that this is executed only when there is something like a move of a finger on the screen and not something like a hit or tap. Any idea how can I achieve what I want?
In this case you should not modify the velocity directly. This can result in unrealistic behavior. I would recommend you to use rigidbody.AddForce( direction : Vector3 ). Add your functionality inside an Update Loop and use a break; to leave the foreach if you want that the force is added only once and not for every single finger on the display.