How to slow character down when moving into a specific area(tilemap?) - c#

Here is my script to make the character move
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Movement : MonoBehaviour
{
Vector3 moveDelta;
BoxCollider2D boxCollider;
protected float speed = 2f;
// Start is called before the first frame update
void Start()
{
boxCollider = GetComponent<BoxCollider2D>();
}
// Update is called once per frame
void FixedUpdate()
{
float x = Input.GetAxisRaw("Horizontal");
float y = Input.GetAxisRaw("Vertical");
moveDelta = new Vector3(x,y,0);
if(moveDelta.x<0)
{
transform.localScale = new Vector3(-1,1,1);
}
else if(moveDelta.x>0)
{
transform.localScale = Vector3.one;
}
transform.Translate(moveDelta*Time.deltaTime*speed);
}
}
I draw a tilemap like this,and I want that when character moves into this area,the speed will be slowed down
Here's the image
How can I do about this?

Related

How to prevent speeding of rigidbodies used to control characters

I have a player in unity with the movement controlled by a rigidbody. The movement on the Z axis is kept contstant by the game to keep the player moving forward. However, this means that the rigidbody keeps speeding up so its speed at the start of the game is much slower than the speed at the end of the game. Here is my script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.SceneManagement;
public class Controller : MonoBehaviour
{
[Tooltip("Rigidbody component attached to the player")]
public Rigidbody rb;
public float forwardMax;
public float slowBy;
private float movementX;
private float movementY;
private float gravity = -9.81f;
private bool isJumping = false;
private bool isSlowing = false;
private bool isSpeeding = false;
private float speedX = 100;
private float speedY = 150000;
private float speedZ = 60;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody>();
}
void Update()
{
// if(!controller.isGrounded)
// {
// Vector3 gravityVector = new Vector3(0.0f, gravity, 0.0f);
// rb.AddForce(gravityVector * Time.deltaTime);
// }
}
void OnCollisionEnter(Collision collision)
{
// SceneManager.LoadScene(1);
}
// Update is called once per frame
void OnMove(InputValue movementValue)
{
Vector2 movementVector = movementValue.Get<Vector2>();
movementX = movementVector.x;
movementY = movementVector.y;
}
void OnJump()
{
isJumping = true;
}
void CalculateMovement()
{
if(rb.velocity.z > 20)
{
rb.drag = 20;
}
else
{
rb.drag = 0;
}
Vector3 movement = new Vector3(movementX * speedX, 0.0f, speedZ);
if(isJumping)
{
movement.y += Mathf.Sqrt(speedY * -3.0f * gravity);
isJumping = false;
}
rb.AddForce(movement);
Debug.Log("Speed is " + rb.velocity.z);
}
void FixedUpdate()
{
CalculateMovement();
}
}
Is there a way to keep the forward velocity constant? The problem is worse when the player jumps.
First I tried clamping the forward (z-axis) vector but that had no effect. Then, I tried adding a backward vector onto the total when the forward velocity was above a certain number but this led to it speeding up and slowing down all the time. Then I tried the same thing with the drag on the rigidbody but that had the same effect.
You can use rigidbody.velocity and set it to constant value or whatever you want instead of adding force. By adding force, your character's speed increases.
Also you can use AddForce but you have to tune the force value dynamically according to the current velocity.
rigidbody velocity
How about directly setting the z value you want at the end of FixedUpdate() ?
......
void FixedUpdate()
{
CalculateMovementWithoutZMovement();
rb.velocity = new Vector3 (rb.velocity.x, rb.velocity.y, ConstantZValue);
}

2D character is not moving in Unity, using the keys. Script seems to be correct. Please verify the code and the Inspector

![This is how my Inspector looks like](inspector image)
And here's the script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
public float speed = 10f;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
Vector2 Movement = Vector2.zero;
Movement.y = v;
Movement.x = h;
transform.Translate(Movement * speed * Time.deltaTime);
}
} // class
And no, increasing the speed to check if its just not moving really slow, did not help :(
You need to set correct value in inspector or in start funciton.
void Start()
{
speed = 10f;
}
inspector image

GameObject reflecting off another gameObject error

I am new at Unity/c# and I wanted to make a pong game. I made this by watching a tutorial on youtube. There is no "error" except the ball doesn't move after touching the player.
This is ball code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BallCode : MonoBehaviour
{
private Rigidbody2D rb;
// Start is called before the first frame update
void Start()
{
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
Vector2 position = transform.position;
position.x = position.x - 5.8f * Time.deltaTime;
transform.position = position;
}
}
This is ball bounce code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BallBounce : MonoBehaviour
{
private Rigidbody2D rb;
Vector3 lastVelocity;
// Start is called before the first frame update
void Awake()
{
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
lastVelocity = rb.velocity;
}
private void OnCollisionEnter2D(Collision2D coll)
{
var speed = lastVelocity.magnitude;
var direction = Vector3.Reflect(lastVelocity.normalized, coll.contacts[0].normal);
}
}
And this is player code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
public float moveSpeed = 4.5f;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
float vertical = Input.GetAxis("Vertical");
Vector2 position = transform.position;
position.y = position.y + moveSpeed * vertical * Time.deltaTime;
transform.position = position;
}
}
When I play the game the ball will collide with player, but it won't ricochet.
Your OnCollisionEnter2D method is not doing anything except set local variables that are quickly discarded. You need to make speed and direction variables of the BallCode or BallBounce class, then set up the BallCode class to use those variables in Update() when determining the motions it makes.
You can try adding a 2D rigid body property to the sphere and removing gravity.
Add a C# script to control the movement of the ball and add a 2D collider to the ball.
//Initial velocity
public float speed = 100f;
void Start()
{
this.GetComponent<Rigidbody2D>().AddForce
(Vector2.right * speed);
}
Add a 2D collider:
Add a 2D physical material to the sphere, so that the ball can bounce.
Modify 2D Physical Material Properties.
Added to the sphere's material.
Add player (Square) and control player movement script.
void Update()
{
// The mouse moves with the player
float y = Camer.main.ScreenToWorldPoint
(Input.mousePosition).y
this.transform.position = new Vector3
(transform.position.x,y,0);
}
Add the wall around the screen and the script Wall to control the randomness of the vertical speed and the direction of the ball when the ball collides with the wall.
public class Wall : MonoBehaviour
{
//Initial velocity
public float speed = 100f;
// Triggered when the collision ends
private void OnCollisionExit(Collision2D collision)
{
int r = 1;
if(Random.Range(0, 2) != -1)
{
r *= -1;
}
//add a vertical force
collision.gameObject.GetComponent<Rigidbody2D>().
AddForce(Vector2.up.*speed*r);
}
}
achieve effect:

GameObject rotation based Vector2 direction

I apologize in advance for my english.
I have a 2D GameObject and i want to rotate it forward based on Vector2 direction.
my arrow right now:
https://streamable.com/7kmtig
i would like this:
This code rotates arrow:
float angle = Mathf.Atan2(p.direction.y, p.direction.x) * Mathf.Rad2Deg;
punta.transform.rotation = Quaternion.AngleAxis(angle, -Vector3.forward);
punta is arrow GameObject
I created 2 scripts:
PlayerController:
using System;
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public Camera cam;
Vector2 coordinate2D;
public bool direziona = false;
public Rigidbody2D rb;
public Vector2 direction;
public Vector2 mousePotion;
public float distanza;
// Start is called before the first frame update
void Start()
{
direction = Vector2.zero;
mousePotion = Vector2.zero;
distanza = 0;
rb = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
RaycastHit2D hit = Physics2D.Raycast(Camera.main.ScreenToWorldPoint(Input.mousePosition), Vector2.zero);
if (hit.collider != null)
{
direziona = true;
}
}
if (direziona)
{
mousePotion = Camera.main.ScreenToWorldPoint(Input.mousePosition);
direction = new Vector2(transform.position.x - mousePotion.x, transform.position.y - mousePotion.y).normalized;
distanza = Mathf.Clamp(Vector2.Distance(mousePotion, transform.position) * 5, 0, 12);
direction = direction * distanza;
if (Input.GetMouseButtonUp(0))
{
rb.AddForce(direction, ForceMode2D.Impulse);
direziona = false;
}
}
}
}
DragLineController:
using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;
using TMPro;
using UnityEngine;
public class DragLineController : MonoBehaviour
{
// Start is called before the first frame update
public GameObject player;
public GameObject punta; //sprite arrow
bool ClickPlayer;
LineRenderer _lineRender;
Vector2 startPoint;
Vector2 endPoint;
PlayerController p;
void Start()
{
p = player.GetComponent<PlayerController>();
_lineRender = GetComponent<LineRenderer>();
_lineRender.SetPosition(0, Vector3.zero);
_lineRender.SetPosition(1, Vector3.zero);
}
// Update is called once per frame
void Update()
{
ClickPlayer = player.GetComponent<PlayerController>().direziona;
if (ClickPlayer)
{
startPoint = player.transform.position;
_lineRender.SetPosition(0, startPoint);
float dist =Mathf.Clamp(p.distanza,0,0.3f);
Debug.Log(dist);
endPoint = startPoint + (p.direction * dist);
_lineRender.SetPosition(1, endPoint);
Vector3 FracciaEndPoint = new Vector3(endPoint.x, endPoint.y, -1);
//punta.transform.rotation = Quaternion.LookRotation(p.direction);
punta.transform.position = FracciaEndPoint;
float angle = Mathf.Atan2(p.direction.y, p.direction.x) * Mathf.Rad2Deg;
punta.transform.rotation = Quaternion.AngleAxis(angle, -Vector3.forward);
}
else
{
_lineRender.SetPosition(0, Vector3.zero);
_lineRender.SetPosition(1, Vector3.zero);
}
}
}
Thanks in advance for your availability.
Instead of calculating the rotation for
punta.transform.rotation = Quaternion.AngleAxis(angle, -Vector3.forward);
you could instead simply assign the according axis (I assume the point looks in its Y direction)
punta.transform.up = p.direction;
or .right if instead it points in its local X direction.

Unity - Quaternion.Slerp instantly rotating

I am trying to have my object smoothly rotate on the Z axis from 0 to 180, back and forth on every button press.
The Quaternion.Slerp setup i'm using does not smoothly rotate to the target rotation, rather it instantly jumps to a number close to it. After many button presses that call the Quaternion.Slerp, it it finally halfs works in that it goes from 0 to 180, but still instantly and not smoothly.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public float moveSpeed;
public bool movePlayer;
private float maxMoveSpeed;
public float waitToMove;
Rigidbody2D thisRigidbody;
//SCOOP variables
private GameObject scoop;
private GameObject scoopRotation;
Quaternion currentScoopRotation;
public Quaternion targetScoopRotation;
Quaternion lastScoopRotation;
public float scoopRotateTime;
// Use this for initialization
void Start ()
{
thisRigidbody = gameObject.GetComponent<Rigidbody2D> ();
maxMoveSpeed = moveSpeed;
//SCOOP finders
scoop = GameObject.FindGameObjectWithTag ("Scoop");
currentScoopRotation = scoop.transform.rotation;
}
// Update is called once per frame
void Update ()
{
if(movePlayer)
thisRigidbody.velocity = new Vector2 (moveSpeed, thisRigidbody.velocity.y);
//Rotates SCOOP using Quaternions + Spacebar
if (Input.GetKeyDown(KeyCode.Space)) {
lastScoopRotation = currentScoopRotation;
scoop.transform.transform.rotation = Quaternion.Lerp (currentScoopRotation, targetScoopRotation, scoopRotateTime * Time.time);
currentScoopRotation = targetScoopRotation;
targetScoopRotation = lastScoopRotation;
changeMoveDirection ();
}
}
void changeMoveDirection()
{
moveSpeed *= -1;
}
IEnumerator changeDirectionCO()
{
//thisRigidbody.velocity = new Vector2 (0f,0f);
//moveSpeed = 0;
yield return new WaitForSeconds (waitToMove);
moveSpeed *= -1;
}
}

Categories