Rotate objects with touch in unity - c#

I want to rotate an object with touch in unity. I touch is moved left object should rotate leftward as long as user holds the touch and vice versa.
My code rotates the object correctly as long as touch is moved leftward or rightward. Later if touch movement is stopped and hold, object starts rotating rightward. Here is what i have tried.
{
if (Input.touchCount > 0)
{
touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Began)
{
oldTouchPosition = touch.position;
}
else if (touch.phase == TouchPhase.Moved)
{
if (touch.deltaPosition.x > 10f)
{
rotateLeftward = false;
rotateRightward = true;
}
else if (touch.deltaPosition.x < 10f)
{
rotateRightward = false;
rotateLeftward = true;
}
}
if(rotateLeftward == true )
{
RotateLeftWard();
}
else if (rotateRightward == true)
{
RotateRightWard();
}
}
}
void RotateLeftWard()
{
transform.rotation = Quaternion.Euler(0f, 1 * keepRotateSpeed, 0f) * transform.rotation;
}
void RotateRightWard()
{
transform.rotation = Quaternion.Euler(0f, -1 * keepRotateSpeed, 0f) * transform.rotation;
}

I think there is no code that sets the both rotations to false..

I was able to code a perfect solution for all this using the code below
I hope it will be useful
private Touch touch;
private Vector2 oldTouchPosition;
private Vector2 NewTouchPosition;
[SerializeField]
private float keepRotateSpeed = 10f;
private void Update()
{
RotateThings();
}
private void RotateThings()
{
if (Input.touchCount > 0)
{
touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Began)
{
oldTouchPosition = touch.position;
}
else if (touch.phase == TouchPhase.Moved)
{
NewTouchPosition = touch.position;
}
Vector2 rotDirection = oldTouchPosition - NewTouchPosition;
Debug.Log(rotDirection);
if (rotDirection.x < 0 )
{
RotateRight();
}
else if (rotDirection.x > 0 )
{
RotateLeft();
}
}
}
void RotateLeft()
{
transform.rotation = Quaternion.Euler(0f, 1.5f * keepRotateSpeed, 0f) * transform.rotation;
}
void RotateRight()
{
transform.rotation = Quaternion.Euler(0f, -1.5f * keepRotateSpeed, 0f) * transform.rotation;
}

Same as Gurbrinder Singh posted, but a bit advanced with a deltaThreshold
private Touch touch;
private Vector2 oldTouchPosition;
private Vector2 NewTouchPosition;
[SerializeField]
private float keepRotateSpeed = 10f;
[SerializeField]
private float deltaThreshold = 5f;
private void Update()
{
RotateThings();
}
private void RotateThings()
{
if (Input.touchCount > 0)
{
touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Began)
{
oldTouchPosition = touch.position;
NewTouchPosition = touch.position;
}
else if (touch.phase == TouchPhase.Moved)
{
oldTouchPosition = NewTouchPosition;
NewTouchPosition = touch.position;
}
float delta = Mathf.Abs(oldTouchPosition.x - NewTouchPosition.x);
if (/*touch.phase != TouchPhase.Stationary &&*/ delta >= deltaThreshold)
{
Vector2 rotDirection = oldTouchPosition - NewTouchPosition;
Debug.Log(delta);
if (rotDirection.x < 0)
{
RotateRight();
}
else if (rotDirection.x > 0)
{
RotateLeft();
}
}
}
}
void RotateLeft()
{
transform.rotation = Quaternion.Euler(0f, 1.5f * keepRotateSpeed, 0f) * transform.rotation;
}
void RotateRight()
{
transform.rotation = Quaternion.Euler(0f, -1.5f * keepRotateSpeed, 0f) * transform.rotation;
}

Something like this will work if you want a little more control
private float _lastTouchRot = float.NegativeInfinity;
...
private void UpdateMobile()
{
if (UnityEngine.Input.touchCount == 2)
{
var touch0 = Input.GetTouch(0);
var touch1 = Input.GetTouch(1);
var touchRot = Vector2.SignedAngle(touch0.position - touch1.position, Vector2.right);
if(this._lastTouchRot == float.NegativeInfinity) this._lastTouchRot = touchRot;
var delta = this._lastTouchRot - touchRot;
this._angle += delta;
this._lastTouchRot = touchRot;
if(touch0.phase == TouchPhase.Ended || touch1.phase == TouchPhase.Ended)
this._lastTouchRot = float.NegativeInfinity;
}
}

Related

How can i stop the coroutine immediately in the middle once the player is not looking at any target anymore?

When the player is looking at a target the ui text is enabled true and it's showing some text.
void OnAnimatorIK()
{
if (lookObjs != null)
{
lookObjs.RemoveAll(x => x == null);
InteractableItem primaryTarget = null;
float closestLookWeight = 0;
// Here we find the target which is closest (by angle) to the players view line
allDetectedItems.Clear();
foreach (InteractableItem target in lookObjs)
{
if (target.enabledInteraction == false)
{
continue;
}
Vector3 lookAt = target.transform.position - transform.position;
lookAt.y = 0f;
// Filter out all objects that are too far away
if (lookAt.magnitude > target.distance) continue;
RaycastHit hit;
if (Physics.Raycast(playerEyes.transform.position, target.transform.position - playerEyes.transform.position, out hit, target.distance, ~LayerMask.GetMask("kid_from_space")))
{
if (hit.collider.gameObject == target.gameObject)
{
float dotProduct = Vector3.Dot(new Vector3(transform.forward.x, 0f, transform.forward.z).normalized, lookAt.normalized);
float lookWeight = Mathf.Clamp(dotProduct, 0f, 1f);
if (lookWeight > 0.1f && lookWeight > closestLookWeight)
{
closestLookWeight = lookWeight;
primaryTarget = target;
if (showText && primaryTarget.description != "")
{
StartCoroutine(WaitBeforeShowingText(primaryTarget));
showText = false;
}
}
allDetectedItems.Add(target);
}
else
{
showText = true;
text.text = "";
descriptionTextImage.SetActive(false);
}
}
}
InteractWithTarget(primaryTarget, closestLookWeight);
}
}
This line start the coroutine that showing the text :
StartCoroutine(WaitBeforeShowingText(primaryTarget));
and inside the coroutine
IEnumerator WaitBeforeShowingText(InteractableItem primaryTarget)
{
yield return new WaitForSeconds(1f);
descriptionTextImage.SetActive(true);
text.text = primaryTarget.description;
}
i did it because i wanted to give some delay before showing the text when the player is looking at a target.
the problem is if the coroutine started but before even showing the text i'm rotating the player to NOT looking at any target but because the coroutine started already it will show the text even if the player is not looking anymore at any target.
so the coroutine must be stopped somehow in the middle and show no text.
another possible problem is what if there are two close targets and i move/rotate the player so the target he is looking at will change too fast for the coroutine ?
This is the full code :
using UnityEngine;
using System;
using System.Collections;
using UnityEngine.UI;
using System.Collections.Generic;
using System.Linq;
using TMPro;
[RequireComponent(typeof(Animator))]
public class IKControl : MonoBehaviour
{
public List<InteractableItem> lookObjs = new List<InteractableItem>();
public TextMeshProUGUI text;
public float weightDamping = 1.5f;
public bool RightHandToTarget = false;
public GameObject descriptionTextImage;
public float duration;
private List<InteractableItem> allDetectedItems;
private Animator animator;
private InteractableItem lastPrimaryTarget;
private float lerpEndDistance = 0.1f;
private float finalLookWeight = 0;
private bool transitionToNextTarget = false;
private float t;
private bool showText = true;
private GameObject playerEyes;
void Start()
{
playerEyes = GameObject.Find("rig_head");//"rig_eye.L");
animator = GetComponent<Animator>();
allDetectedItems = new List<InteractableItem>();
t = 0;
}
// Callback for calculating IK
void OnAnimatorIK()
{
if (lookObjs != null)
{
lookObjs.RemoveAll(x => x == null);
InteractableItem primaryTarget = null;
float closestLookWeight = 0;
// Here we find the target which is closest (by angle) to the players view line
allDetectedItems.Clear();
foreach (InteractableItem target in lookObjs)
{
if (target.enabledInteraction == false)
{
continue;
}
Vector3 lookAt = target.transform.position - transform.position;
lookAt.y = 0f;
// Filter out all objects that are too far away
if (lookAt.magnitude > target.distance) continue;
RaycastHit hit;
if (Physics.Raycast(playerEyes.transform.position, target.transform.position - playerEyes.transform.position, out hit, target.distance, ~LayerMask.GetMask("kid_from_space")))
{
if (hit.collider.gameObject == target.gameObject)
{
// First object hit was the target so there is a clear line of sight
//Debug.DrawRay(playerEyes.transform.position, Vector3.forward, Color.red);
float dotProduct = Vector3.Dot(new Vector3(transform.forward.x, 0f, transform.forward.z).normalized, lookAt.normalized);
float lookWeight = Mathf.Clamp(dotProduct, 0f, 1f);
if (lookWeight > 0.1f && lookWeight > closestLookWeight)
{
closestLookWeight = lookWeight;
primaryTarget = target;
if (showText && primaryTarget.description != "")
{
StartCoroutine(WaitBeforeShowingText(primaryTarget));
showText = false;
}
}
allDetectedItems.Add(target);
}
else
{
showText = true;
text.text = "";
descriptionTextImage.SetActive(false);
}
}
}
InteractWithTarget(primaryTarget, closestLookWeight);
}
}
private void InteractWithTarget(InteractableItem primaryTarget, float closestLookWeight)
{
if (primaryTarget != null)
{
if ((lastPrimaryTarget != null) && (lastPrimaryTarget != primaryTarget) && (finalLookWeight > 0f))
{
// Here we start a new transition because the player looks already to a target but
// we have found another target the player should look at
transitionToNextTarget = true;
}
}
// The player is in a neutral look position but has found a new target
if ((primaryTarget != null) && !transitionToNextTarget)
{
if (primaryTarget.IsAnyAction())
{
RightHandToTarget = true;
}
lastPrimaryTarget = primaryTarget;
finalLookWeight = Mathf.Lerp(finalLookWeight, 1f, Time.deltaTime * weightDamping);
float bodyWeight = finalLookWeight * .1f;
animator.SetLookAtWeight(finalLookWeight, bodyWeight, 1f);
animator.SetLookAtPosition(primaryTarget.transform.position);
if (RightHandToTarget && primaryTarget.IsAnyAction())
{
Vector3 relativePos = primaryTarget.transform.position - transform.position;
Quaternion rotationtoTarget = Quaternion.LookRotation(relativePos, Vector3.up);
if (primaryTarget.interactableMode == InteractableItem.InteractableMode.ActionWithoutThrow)
{
animator.SetIKRotationWeight(AvatarIKGoal.RightHand, finalLookWeight);
animator.SetIKRotation(AvatarIKGoal.RightHand, rotationtoTarget);
animator.SetIKPositionWeight(AvatarIKGoal.RightHand, finalLookWeight * 1f * closestLookWeight);
animator.SetIKPosition(AvatarIKGoal.RightHand, primaryTarget.transform.position);
}
if (primaryTarget.interactableMode == InteractableItem.InteractableMode.Action)
{
animator.SetIKRotationWeight(AvatarIKGoal.RightHand, finalLookWeight);
animator.SetIKRotation(AvatarIKGoal.RightHand, rotationtoTarget);
animator.SetIKPositionWeight(AvatarIKGoal.RightHand, finalLookWeight * 0.1f * closestLookWeight);
animator.SetIKPosition(AvatarIKGoal.RightHand, primaryTarget.transform.position);
}
}
}
// Let the player smoothly look away from the last target to the neutral look position
if ((primaryTarget == null && lastPrimaryTarget != null) || transitionToNextTarget)
{
finalLookWeight = Mathf.Lerp(finalLookWeight, 0f, t / duration);//Time.deltaTime * weightDamping);
t += Time.deltaTime;
float bodyWeight = finalLookWeight * .1f;
animator.SetLookAtWeight(finalLookWeight, bodyWeight, 1f);
animator.SetLookAtPosition(lastPrimaryTarget.transform.position);
if (RightHandToTarget)
{
Vector3 relativePos = lastPrimaryTarget.transform.position - transform.position;
Quaternion rotationtoTarget = Quaternion.LookRotation(relativePos, Vector3.up);
animator.SetIKRotationWeight(AvatarIKGoal.RightHand, finalLookWeight);
animator.SetIKRotation(AvatarIKGoal.RightHand, rotationtoTarget);
animator.SetIKPositionWeight(AvatarIKGoal.RightHand, finalLookWeight * 0.5f * closestLookWeight);
animator.SetIKPosition(AvatarIKGoal.RightHand, lastPrimaryTarget.transform.position);
}
if (finalLookWeight < lerpEndDistance)
{
showText = true;
text.text = "";
descriptionTextImage.SetActive(false);
transitionToNextTarget = false;
finalLookWeight = 0f;
lastPrimaryTarget = null;
transform.rotation = Quaternion.Euler(0, transform.eulerAngles.y, 0);
}
}
}
IEnumerator WaitBeforeShowingText(InteractableItem primaryTarget)
{
yield return new WaitForSeconds(1f);
descriptionTextImage.SetActive(true);
text.text = primaryTarget.description;
}
}
To stop a Coroutine, call StopCoroutine(WaitBeforeShowingText);
Here is the doc :
https://docs.unity3d.com/ScriptReference/MonoBehaviour.StopCoroutine.html

Platformer Double-Jump and Dash Not Working

Working on a platformer where as the player moves over an energy orb, they can choose to fuel either a double jump or a dash. No errors according to unity, but when I press the corresponding keys for my double jump and dash, neither work. Simply nothing happens. Oh and btw my character randomly freezes and I have to tap the movement key again to get him to continue moving this is also a new issue so may be related. I am very new to all this.
public class playerMovement : MonoBehaviour
{
[SerializeField] private float speed;
[SerializeField] int dashEnergy = 1;
[SerializeField] int doubleJumpEnergy = 1;
private Rigidbody2D body;
private Animator anim;
private int jumpCount;
private void Awake()
{
body = GetComponent<Rigidbody2D>();
}
private void Update()
{
//Left-Right Movement
float horizontalInput = Input.GetAxis("Horizontal");
if(Input.GetKey(KeyCode.Space) && jumpCount == 0)
{
jump();
jumpCount += 1;
}
body.velocity = new Vector2(horizontalInput*speed, body.velocity.y);
//Character Turns Towards Movement Direction
if (horizontalInput > 0.01f)
transform.localScale = new Vector3(-5, 5, 5);
if (horizontalInput < -0.01f)
transform.localScale = new Vector3(5,5,5);
//Dash & doubleJump
void doubleJump()
{
if(Input.GetKey(KeyCode.Space)&&jumpCount==1 && doubleJumpEnergy==1)
{
jump();
doubleJumpEnergy -= 1;
}
}
void Dash()
{
if(Input.GetKey(KeyCode.LeftShift) && dashEnergy == 1)
{
body.velocity = new Vector2(horizontalInput*speed*60, body.velocity.y);
dashEnergy -=1;
}
}
}
public void jump()
{
body.velocity = new Vector2(body.velocity.x, speed);
}
private void OnCollisionEnter2D(Collision2D collision)
{
if(collision.gameObject.tag == "EnergyBubble" && Input.GetKey(KeyCode.V))
{
dashEnergy += 1;
}
if(collision.gameObject.tag == "EnergyBubble" && Input.GetKey(KeyCode.C))
{
doubleJumpEnergy += 1;
}
if (collision.gameObject.tag == "Ground")
{
jumpCount=0;
}
}
}
Firstly, all physics operations should be used from fixedUpdate method, for example:
void FixedUpdate()
{
if (Input.GetButtonDown("Space"))
rb.velocity = new Vector2(0, 10);
}
It's needs for smoothly physics movement.
Or call your own method from it:
void FixedUpdate()
{
if (Input.GetButtonDown("Space"))
jump();
}
Then you have a bug in condition check statements, you have to use:
//Dash & doubleJump
if (Input.GetKey(KeyCode.Space) && jumpCount == 1 && doubleJumpEnergy >= 1)
{
body.velocity = new Vector2(0, 2);
doubleJumpEnergy -= 1;
}
if (Input.GetKey(KeyCode.LeftShift) && dashEnergy >= 1)
{
body.velocity = new Vector2(horizontalInput * speed * 60, body.velocity.y);
dashEnergy -= 1;
}
Problem with a condition check statements, you need to have ">=" operator: dashEnergy >= 1 and doubleJumpEnergy >= 1 instead ==

Why does my dash only function properly if you aren't moving?

Here is the complete player controller file.
using UnityEngine;
public class PlayerCont : MonoBehaviour
{
[Header("Movement Variables")]
public float moveSpeed;
private float speed;
public float maxSpeed;
public float acceleration;
public float dropSpeed;
public float slideSpeed;
public int direction = 1;
[Header("Jump Variables")]
public float jumpForce;
public int extraJumps;
private float jumpTimeCounter;
public float jumpTime;
private bool isJumping;
private int jumpNum;
[Header("Dash Variables")]
public float dashSpeed;
public float dashLength = .5f;
public float dashCooldown = 1f;
private float dashCounter;
public float dashCoolCounter;
private KeyCode _lastKeyCode;
private float doubleTapTime = 0.05f;
private bool doubleTap;
public bool isDashing;
public float dashTime;
public float maxDashTime;
[Header("GroundCheck Variables")]
public Transform groundCheck;
public float checkRadius;
public LayerMask whatIsGround;
[Header("Debug Variables")]
public Rigidbody2D rb;
public float moveInputX;
public float moveInputY;
public bool facingRight = true;
public bool isGrounded;
public bool downKey;
public float rbxVel;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
speed = moveSpeed;
jumpNum = extraJumps;
}
void FixedUpdate()
{
}
// Update is called once per frame
void Update()
{
moveInputX = Input.GetAxisRaw("Horizontal");
moveInputY = Input.GetAxisRaw("Vertical");
isGrounded = Physics2D.OverlapCircle(groundCheck.position, checkRadius, whatIsGround);
KeyChecks();
Jump();
GroundPound();
Move();
Dash();
}
void KeyChecks()
{
//restricts movement in Y to only be downward
if (moveInputY > 0)
{
moveInputY = 0;
}
//checks for player drop
if (!isGrounded && moveInputY < 0)
{
downKey = true;
}
else
{
downKey = false;
}
//changes direction relative to keypress
if (Input.GetKeyDown(KeyCode.A))
{
direction = -1;
}
if (Input.GetKeyDown(KeyCode.D))
{
direction = 1;
}
}
void Jump()
{
//sets jump number to user specified amount after touching ground
if (isGrounded)
{
extraJumps = jumpNum;
}
//jumps and decrements extrajumps by 1
if (Input.GetKeyDown(KeyCode.Space) && !downKey && extraJumps > 0)
{
isJumping = true;
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
extraJumps--;
}
//basic jump off of ground
else if (Input.GetKeyDown(KeyCode.Space) && extraJumps == 0 && isGrounded && !downKey)
{
isJumping = true;
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
}
//checks for longkeypress of spacebar and increases length of jump
if (Input.GetKey(KeyCode.Space) && extraJumps > 1 && isJumping) // allows a hold down increase to jump while grounded
{
if (jumpTimeCounter > 0)
{
rb.velocity = new Vector2(rb.velocity.x, jumpForce);
jumpTimeCounter -= Time.deltaTime;
}
else
{
jumpTimeCounter = jumpTime;
isJumping = false;
}
}
}
void GroundPound()
{
//ground pound keypress check
if (!isGrounded && Input.GetKeyDown(KeyCode.S))
{
if (!doubleTap && doubleTapTime > Time.time && _lastKeyCode == KeyCode.S)
{
rb.velocity = new Vector2(rb.velocity.x, -1 * dropSpeed);
Debug.Log("dashing right");
}
else
{
doubleTapTime = Time.time + 0.5f;
}
_lastKeyCode = KeyCode.S;
}
}
void Move()
{
//changes movement relative to input
if (!isDashing)
{
if (isGrounded && Input.GetKey(KeyCode.S))
{
rb.velocity = new Vector2(rb.velocity.x * .999f, rb.velocity.y);
}
else if (moveInputX == 0 && isGrounded)
{
speed = moveSpeed;
rb.velocity = new Vector2(rb.velocity.x * .99f, rb.velocity.y);
}
else if (moveInputX == 0 && !isGrounded)
{
speed = moveSpeed;
}
else
{
rb.velocity = new Vector2(moveInputX * speed, moveInputY / 10 + rb.velocity.y);
}
}
//checks player velocity
rbxVel = rb.velocity.x;
//increases speed relative to input direction
if (moveInputX > 0 || moveInputX < 0)
{
speed += acceleration;
}
//caps speed
if (speed > maxSpeed)
{
speed = maxSpeed;
}
//caps min speed
if (speed < moveSpeed)
{
speed = moveSpeed;
}
}
void Dash()
{
if (Input.GetKeyDown(KeyCode.LeftShift))
{
isDashing = true;
if (isDashing && dashCoolCounter <= 0)
{
dashTime -= Time.deltaTime;
dashCoolCounter = dashCooldown;
rb.velocity = new Vector2(dashSpeed * direction, rb.velocity.y);
Debug.Log("Dash Started");
}
}
else
{
dashTime = maxDashTime;
isDashing = false;
Debug.Log("No Dash");
}
//resets dash cooldown
if (dashCoolCounter > 0)
{
dashCoolCounter -= Time.deltaTime;
}
}
void Flip()
{
facingRight = !facingRight;
Vector3 Scaler = transform.localScale;
Scaler.x *= -1;
transform.localScale = Scaler;
}
}
When using the keys for movement (A, S) the dash doesn't function. Oddly enough the code is executing (I see my debug statement in console) but nothing physically changes.
When rewriting the code for the dash from: rb.velocity = new Vector2(dashSpeed * direction, rb.velocity.y) to: rb.velocity = dashspeed the dash will work without issue. The only downside to that is that the Y component of the RigidBody is being manipulated as well.
This has been an issue for days now, and I am just rewriting the post.
Any and all help is welcomed.
You're setting isDashing = false too soon. It gets set to false as soon as you let go of Shift which allows Move to execute its code and change your rigidbody's velocity back to normal move.
Didn't test this, but give it a shot and see if it works the way you want it to.
void Dash()
{
if (Input.GetKeyDown(KeyCode.LeftShift))
{
if (!isDashing && dashCoolCounter <= 0)
{
isDashing = true;
dashTime = 0;
dashCoolCounter = dashCooldown;
rb.velocity = new Vector2(dashSpeed * direction, rb.velocity.y);
Debug.Log("Dash Started");
}
else if(isDashing)
{
rb.velocity = new Vector2(dashSpeed * direction, rb.velocity.y);
dashTime += Time.deltaTime;
if(dashTime >= maxDashTime)
{
isDashing = false;
Debug.Log("No Dash");
}
}
}
// resets dash cooldown
if (dashCoolCounter > 0)
{
dashCoolCounter -= Time.deltaTime;
}
}

Unity jump issue

I make 3rd person game, where i have script for control model of my character.
Problem is that when i jump and don't push any button he stack in the air, but if i jump with pushing controlling button he worked normally.
Thanks in advance.
Player controller script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(CharacterController))]
public class RelativeMovement : MonoBehaviour
{
[SerializeField] private Transform target;
public float rotSpeed = 5.0f;
public float moveSpeed = 6.0f;
public float jumpSpeed = 15.0f;
public float gravity = -9.8f;
public float terminalVelocity = -20.0f;
public float minFall = -1.5f;
private float _vertSpeed;
private CharacterController _charController;
private ControllerColliderHit _contact;
void Start()
{
_vertSpeed = minFall;
_charController = GetComponent<CharacterController>();
}
void Update()
{
Vector3 movement = Vector3.zero;
float horInput = Input.GetAxis("Horizontal");
float vertInput = Input.GetAxis("Vertical");
if(horInput != 0 || vertInput != 0)
{
movement.x = horInput * moveSpeed;
movement.z = vertInput * moveSpeed;
movement = Vector3.ClampMagnitude(movement, moveSpeed);
Quaternion tmp = target.rotation;
target.eulerAngles = new Vector3(0, target.eulerAngles.y, 0);
movement = target.TransformDirection(movement);
target.rotation = tmp;
Quaternion direction = Quaternion.LookRotation(movement);
transform.rotation = Quaternion.Lerp(transform.rotation,
direction, rotSpeed * Time.deltaTime);
bool hitGround = false;
RaycastHit hit;
if(_vertSpeed < 0 && Physics.Raycast(transform.position, Vector3.down, out hit))
{
float check =
(_charController.height + _charController.radius) / 1.9f;
hitGround = hit.distance <= check;
}
if(hitGround)
{
if (Input.GetButtonDown("Jump"))
{
_vertSpeed = jumpSpeed;
}
else
{
_vertSpeed = minFall;
}
}
else
{
_vertSpeed += gravity * 5 * Time.deltaTime;
if(_vertSpeed < terminalVelocity)
{
_vertSpeed = terminalVelocity;
}
if(_charController.isGrounded)
{
if(Vector3.Dot(movement, _contact.normal) < 0)
{
movement = _contact.normal * moveSpeed;
}
else
{
movement += _contact.normal * moveSpeed;
}
}
}
movement.y = _vertSpeed;
movement *= Time.deltaTime;
_charController.Move(movement);
}
}
void OnControllerColliderHit(ControllerColliderHit hit)
{
_contact = hit;
}
}
Jesus photo:
enter image description here
I didn't go through all of the code but I can immediately see what can cause the problem you describe:
your entire logic happen under this if statement:
if(horInput != 0 || vertInput != 0)
So everything inside this logic block will happen only when you actively press a movement button.
You can remove it (or better yet, close the if block at the right spot.. I think it would be 2 lines down)
The answer of this question is:
if((horInput == 0 || vertInput == 0) || (horInput != 0 && vertInput != 0))
{
movement.x = horInput * moveSpeed;
movement.z = vertInput * moveSpeed;
if(horInput != 0 || vertInput != 0)
{
movement = Vector3.ClampMagnitude(movement, moveSpeed);
Quaternion tmp = target.rotation;
target.eulerAngles = new Vector3(0, target.eulerAngles.y, 0);
movement = target.TransformDirection(movement);
target.rotation = tmp;
Quaternion direction = Quaternion.LookRotation(movement);
transform.rotation = Quaternion.Lerp(transform.rotation,
direction, rotSpeed * Time.deltaTime);
}
Thanks Joe

transform.Rotate(0f, 180f, 0f); rotates the 2D sprite, but not it's children

I'm trying to achieve firing from a 2D Player, attached the "spawn point" and made it a child of the Player, when I try to flip the sprite it works, but it does not flip the "spawn point" so when I turn left, my "spawn point" is still looking right, so when I shoot, the bullets go to the left, not to the right.
Full script:
public class PlayerController : MonoBehaviour
{
void FixedUpdate()
{
RaycastHit2D hit = Physics2D.BoxCast(this.transform.position, new Vector2(0.4f, 0.1f), 0f, Vector2.down, groundCheckRadius, groundMask); //using this for a bigger and more accurate ground check
isTouchingGround = (hit.collider != null) ? true : false;
movementInput = Input.GetAxis("Horizontal");
CheckIfStuck(); //Checks if Mario is trying to walk into the wall and get stuck
if (!isDead)
{
if ((playerRigidbody2D.velocity.x > 0 && !isFacingRight) || (playerRigidbody2D.velocity.x < 0 && isFacingRight))
{
playerAnimator.SetBool("turning", true);
}
else
{
playerAnimator.SetBool("turning", false);
}
float movementForceMultiplier = Mathf.Max(maxHorizontalSpeed - Mathf.Abs(playerRigidbody2D.velocity.x), 1);
playerRigidbody2D.AddForce(new Vector2(movementInput * movementForce * movementForceMultiplier, 0));
playerRigidbody2D.velocity = new Vector2(Mathf.Clamp(playerRigidbody2D.velocity.x, -maxHorizontalSpeed, maxHorizontalSpeed), Mathf.Clamp(playerRigidbody2D.velocity.y, -maxVerticalSpeed, maxVerticalSpeed));
if (Input.GetKeyDown(KeyCode.Space))
{
if (isTouchingGround)
{
//Play Jump sound
if (!poweredUp)
audioSource.PlayOneShot(smallJumpSound);
else
audioSource.PlayOneShot(bigJumpSound);
isJumping = true;
playerRigidbody2D.velocity = new Vector2(playerRigidbody2D.velocity.x, jumpVelocity);
jumpTimeCounter = jumpTime;
}
}
if (jumpTimeCounter > 0 && isJumping)
if (Input.GetKey(KeyCode.Space))
{
jumpTimeCounter -= Time.deltaTime;
{
playerRigidbody2D.velocity = new Vector2(playerRigidbody2D.velocity.x, jumpVelocity);
}
}
if (Input.GetKeyUp(KeyCode.Space))
{
isJumping = false;
jumpTimeCounter = 0;
}
playerAnimator.SetFloat("movementSpeed", Mathf.Abs(playerRigidbody2D.velocity.x));
playerAnimator.SetBool("touchingGround", isTouchingGround);
}
if (movementInput > 0 && !isFacingRight)
{
FlipSprite();
}
else if (movementInput < 0 && isFacingRight)
{
FlipSprite();
}
}
void FlipSprite()
{
isFacingRight = !isFacingRight;
//Vector3 tempScale = transform.localScale;
//tempScale.x *= -1;
//transform.localScale = tempScale;
transform.Rotate(0f, 180f, 0f);
}
}
Flip method:
void FlipSprite()
{
isFacingRight = !isFacingRight;
//Vector3 tempScale = transform.localScale;
//tempScale.x *= -1;
//transform.localScale = tempScale;
transform.Rotate(0f, 180f, 0f);
}

Categories