change direction into random direction on collision Unity2D - c#

I'm new to unity and I'm trying to create a game where there's a ball that can move
in the direction by dragging and releasing on the screen and that change direction randomly when hitting a prefab, I already created that kind of movement but couldn't figure out how to make the ball change direction randomly when hitting the prefab.
Sorry if this isn't the right place to ask.
Here's my script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Player : MonoBehaviour
{
[SerializeField] private float power = 2;
[SerializeField] private Vector2 minPow, maxPow;
public Vector3 force;
private Vector3 startPoint, endPoint;
private Rigidbody2D rb;
private Camera cam;
private Aim aim;
void Start()
{
cam = Camera.main;
rb = GetComponent<Rigidbody2D>();
aim = GetComponent<Aim>();
}
void Update()
{
if(Input.GetMouseButtonDown(0))
{
startPoint = cam.ScreenToWorldPoint(Input.mousePosition);
startPoint.z = 15;
}
if(Input.GetMouseButton(0))
{
Vector3 currentPos = cam.ScreenToWorldPoint(Input.mousePosition);
startPoint.z = 15;
aim.RenderLine(startPoint, currentPos);
}
if(Input.GetMouseButtonUp(0))
{
endPoint = cam.ScreenToWorldPoint(Input.mousePosition);
endPoint.z = 15;
force = new Vector3(Mathf.Clamp(startPoint.x - endPoint.x, minPow.x, maxPow.x), Mathf.Clamp(startPoint.y - endPoint.y, minPow.y, maxPow.y));
rb.AddForce(force * power, ForceMode2D.Impulse);
aim.EndLine();
}
}
public void BoostUp(float pow)
{
rb.velocity *= pow;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Boost : MonoBehaviour
{
[SerializeField] float pow;
private void OnTriggerEnter2D(Collider2D other)
{
if(other.tag == "Player")
{
Player player = other.GetComponent<Player>();
if(player != null)
{
player.BoostUp(pow);
Destroy(this.gameObject);
}
}
}
}

You can get a random angle in radians using Random.Range(0f, 2f * Mathf.PI) and then pass it to Mathf.Cos and Mathf.Sin functions to get a direction with that angle:
float angle = Random.Range( 0f, 2f * Mathf.PI );
Vector2 direction = new Vector2( Mathf.Cos( angle ), Mathf.Sin( angle ) );

Related

Unity player movement on moving planet

I am making a game involving orbital physics. I was successfully able to implement this with a slightly modified version of Brackeys gravity tutorial https://youtu.be/Ouu3D_VHx9o, this is the code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class gravity : MonoBehaviour
{
public GameObject self;
public Rigidbody rb;
public Vector3 initialVelocity;
const float G = 66.74f;
public static List<gravity> Attractors;
public bool isAttractable;
private void Awake()
{
rb.AddForce(initialVelocity);
}
private void FixedUpdate()
{
//planets
if (isAttractable == false)
{
foreach (gravity attractor in Attractors)
{
if (attractor != this)
Attract(attractor);
}
}
//players, spaceships, astroids, ect
if (isAttractable == true)
{
foreach (gravity attractor in Attractors)
{
if (attractor != this)
Attract(attractor);
}
}
}
void OnEnable()
{
if( isAttractable == false)
{
if (Attractors == null)
Attractors = new List<gravity>();
Attractors.Add(this);
}
}
void OnDisable()
{
if (isAttractable == false)
{
Attractors.Remove(this);
}
}
void Attract(gravity objToAttract)
{
Rigidbody rbToAttract = objToAttract.rb;
Vector3 direction = -1 * (rb.position - rbToAttract.position);
Vector3 Force = direction.normalized * (G * ((rb.mass * rbToAttract.mass) / direction.sqrMagnitude));
rb.AddForce(Force);
}
public GameObject GetClosestPlanet()
{
GameObject close = null;
float minDist = Mathf.Infinity;
foreach (gravity attracor in Attractors)
{
float dist = Vector3.Distance(attracor.transform.position, transform.position);
if (dist < minDist)
{
close = attracor.transform.gameObject;
minDist = dist;
}
}
return close;
}
}
Then for player movement I used (and modified) Sebastian Lagues tutorial https://youtu.be/TicipSVT-T8,
this resulted in this code for the player controller:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class playerController : MonoBehaviour
{
public float mouseSensitivityX = 250f;
public float mouseSensitivityY = 250f;
Transform cameraT;
float verticalLookRot;
private Rigidbody rb;
Vector3 moveAmount;
Vector3 smootgMoveVelocity;
public float moveSpeed = 15;
public float jumpForce = 220;
public LayerMask groundedMask;
public bool grounded;
public GameObject currentPlanet;
private gravity playerGravity;
private void Awake()
{
rb = GetComponent<Rigidbody>();
playerGravity = GetComponent<gravity>();
Cursor.lockState = CursorLockMode.Locked;
cameraT = Camera.main.transform;
}
void Update()
{
currentPlanet = playerGravity.GetClosestPlanet();
//camera
transform.Rotate(Vector3.up * Input.GetAxis("Mouse X") * Time.deltaTime * mouseSensitivityX);
verticalLookRot += Input.GetAxis("Mouse Y") * Time.deltaTime * mouseSensitivityY;
verticalLookRot = Mathf.Clamp(verticalLookRot, -60, 60);
cameraT.localEulerAngles = Vector3.left * verticalLookRot;
//move input
Vector3 moveDir = new Vector3(Input.GetAxisRaw("Horizontal"), 0, Input.GetAxisRaw("Vertical")).normalized;
Vector3 targetMoveAmount = moveDir * moveSpeed;
moveAmount = Vector3.SmoothDamp(targetMoveAmount, targetMoveAmount, ref smootgMoveVelocity, .15f);
//level on planet
if(currentPlanet != null)
{
transform.rotation = Quaternion.FromToRotation(transform.up, (transform.position - currentPlanet.transform.position).normalized) * transform.rotation;
}
//jump
if (Input.GetButtonDown("Jump"))
{ if(grounded)
{
rb.AddForce(transform.up * jumpForce);
print("u jumped");
}
}
}
private void FixedUpdate()
{
//move
rb.MovePosition(rb.position + transform.TransformDirection(moveAmount) * Time.fixedDeltaTime);
//check if on ground
Ray ray = new Ray(transform.position, -transform.up);
RaycastHit hit;
grounded = Physics.Raycast(ray, out hit, transform.localScale.y + 1.1f, groundedMask);
}
}
Now for the issue, this systems works fine when the planet the player is walking on is stationary. As in there are no other attracting bodys in the system and the planet has no initial velocity. However if the planet is moving the player will bounce up and down uncontrollably and will not be able to walk a certain distance away from the planets farthest point from its direction of movement. Here is a recording of this: https://youtu.be/noMekosb7CU
Does anyone know what is causing the bouncing and walking restrictions and how I can fix it?
Some notes on suggested solutions that haven't worked:
-set the planet as the players parent object, same results
-increase players mass, same results
-set the players velocity to += the planets velocity, same results or player goes into infinity
For me it seems to be working "correctly".
Looking like your player is attracted correctly and when the planet moves, your player is quickly moving towards the planet.
I think you could temporarily assign the player as a child gameobject to the planet he's walking on and he should probably move correctly along the planet coordinates and not on global coordinates. (If it works, you could just always assign the player as a child gameObject to every new planet that he visits)

2D Movement Bug in Unity

I'm trying to make a 2D Space Shooter game in Unity but stumbled upon a bug that needs fixing. I'm using Unity 2021.1.0f1 and the new Input System in Unity and I'm trying to implement movement for my character. When I press the WASD keys, my character for some reason moves 15 units on every press. I don't want that, I want smooth movement for my character. Here's my code:
using UnityEngine;
using UnityEngine.InputSystem;
public class Ship : MonoBehaviour
{
private Keyboard _keyboard = Keyboard.current;
[SerializeField] private float speed = 0.25f;
[SerializeField] private GameObject projectile;
[SerializeField] private Rigidbody2D rigidbody;
private void Start()
{
if (speed == null)
{
Debug.Log("Please assign a a value to \"speed\".");
}
if (rigidbody == null)
{
Debug.Log("Please assign a a value to \"rigidbody\".");
}
if (projectile == null)
{
Debug.Log("Please assign a a value to \"projectile\".");
}
}
public void OnMove(InputAction.CallbackContext context)
{
Vector2 movementVector = context.ReadValue<Vector2>();
Vector3 move = Quaternion.Euler(0.0f, transform.eulerAngles.y, 0.0f) * new Vector3(movementVector.x, movementVector.y, 0.0f);
transform.position += move * speed;
}
public void OnFire(InputAction.CallbackContext context)
{
Vector2 spawnPosition = new Vector2(transform.position.x, 0.5f);
if (context.performed)
{
Instantiate(projectile, spawnPosition, Quaternion.identity);
}
}
}
Anyone?
I have been working on the same project lately and I used the following code for the movement of my spaceship and it moves smoothly :
void C_Movement(){
//Input controller (direction)
float horizontalInput = Input.GetAxis("Horizontal");
float verticalInput = Input.GetAxis("Vertical") ;
Vector3 directionX = new Vector3(horizontalInput,0,0) ;
transform.Translate(directionX* Time.deltaTime * 13) ;
Vector3 directionY = new Vector3(0,verticalInput,0) ;
transform.Translate(directionY* Time.deltaTime * 13) ;
}

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.

Is There A Way To Use The Axes Input From A Joystick To Rotate A GameObject Around A Point?

I have a gun and a player (cube) on a 2d Unity Project. I have made a script that rotates the gun around the player depending on the position of the mouse on the screen. I was wondering if I could adapt this script to make the gun rotate depending on the Horizontal and Vertical values of a joystick?
this is what I have so far (don't worry about my terrible spelling):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WeaponAming : MonoBehaviour
{
public GameObject bullet;
public GameObject spawn;
public ParticleSystem mf1;
public ParticleSystem mf2;
public float speed = .5f;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
turning();
if (Input.GetButtonDown("XButton"))
{
shoot();
}
}
void turning()
{
Vector3 mousePos = Input.mousePosition;
mousePos.z = 10;
mousePos = Camera.main.ScreenToWorldPoint(mousePos);
Vector2 direc = new Vector2(mousePos.x - transform.position.x, mousePos.y - transform.position.y);
transform.right = direc;
}
void shoot()
{
mf1.Play();
mf2.Play();
GameObject projectile = (GameObject)Instantiate(bullet, spawn.transform.position, Quaternion.identity);
projectile.transform.right = transform.right;
}
}
You can make a direction from Input.GetAxisRaw("Horizontal") and Input.GetAxisRaw("Horizontal") if at least one is nonzero, and then set the transform's right to that direction:
void turning()
{
float horiz = Input.GetAxisRaw("Horizontal");
float vert = Input.GetAxisRaw("Vertical");
if (horiz != 0 || vert != 0)
{
Vector2 direc = new Vector2(horiz, vert);
transform.right = direc;
}
}
If you would like to invert the controls vertically, negate vert:
void turning()
{
float horiz = Input.GetAxisRaw("Horizontal");
float vert = Input.GetAxisRaw("Vertical");
if (horiz != 0 || vert != 0)
{
Vector2 direc = new Vector2(horiz, -vert);
transform.right = direc;
}
}

Enemy movement just on some portion of ground 2D Unity

Can I make my enemy move just on some suspended blocks? I have a script but my enemy fall of them and doesn't stop when is not any block around . I am bound to put blocks higher just to stop his fall?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Enemy : MonoBehaviour
{
private float latestDirectionChangeTime;
private readonly float directionChangeTime = 3f;
private float characterVelocity = 2f;
private Vector2 movementDirection;
private Vector2 movementPerSecond;
void Start()
{
latestDirectionChangeTime = 0f;
calcuateNewMovementVector();
}
void calcuateNewMovementVector()
{
//create a random direction vector with the magnitude of 1, later multiply it with the velocity of the enemy
movementDirection = new Vector2(Random.Range(-1.0f, 1.0f), Random.Range(-1.0f, 1.0f)).normalized;
movementPerSecond = movementDirection * characterVelocity;
}
void Update()
{
//if the changeTime was reached, calculate a new movement vector
if (Time.time - latestDirectionChangeTime > directionChangeTime)
{
latestDirectionChangeTime = Time.time;
calcuateNewMovementVector();
}
//move enemy:
transform.position = new Vector2(transform.position.x + (movementPerSecond.x * Time.deltaTime),
transform.position.y + (movementPerSecond.y * Time.deltaTime));
}
}

Categories