Unity 2D- Rays not going in the right direction - unity3d

I have a game object which is supposed to shoot a beam in several directions. I want to keep it as flexible as possible so I added several targets, which a script will draw a ray(from the game object to the target). I have used the position variable of the target's transforms but that just caused all the rays to go off to a strange direction but did slightly change when i moved around. Then i tried the local position of the targets but that caused all the rays to go in their original direction, not accounting for a change in rotation.
Here is the code for the laser's script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Laser : MonoBehaviour {
private LineRenderer Linerenderer;
public List<Transform> rays;
void Start()
{
Physics2D.queriesStartInColliders = false;
}
void Update () {
foreach (Transform tran in rays)
{
RaycastHit2D hit = Physics2D.Raycast(transform.position, tran.position,20);
Debug.DrawLine(transform.position, hit.point);
}
}
}
Screenshots:
-Using world positions:
-Using local positions:

The Physics2D.Raycast() method's second parameter you are specifying is wrong: it should not be a position in space, but a direction. The second parameter for the Debug.DrawRay() method is also a direction, not a point in space.
Try the following:
void Update () {
foreach (Transform tran in rays)
{
Vector2 direction = (tran.position - transform.position).normalized;
RaycastHit2D hit = Physics2D.Raycast(transform.position, direction, 20);
Vector2 rayDirection = hit.point - transform.position;
Debug.DrawRay(transform.position, rayDirection);
}
}

Thank you, after bit of messing around I was finally able to get it to work.
If anyone else needs help with something similar (Dynamic ray-casting).
Here is the final code(you might have to edit it slightly):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Laser : MonoBehaviour {
private LineRenderer Linerenderer;
public List<Transform> rays;
void Start()
{
Physics2D.queriesStartInColliders = false;
}
void Update()
{
foreach (Transform tran in rays)
{
Debug.DrawRay(new Vector3(1, 1, 0), new Vector3(-1, -1, 0));
Vector2 direction = (tran.position - transform.position).normalized;
RaycastHit2D hit = Physics2D.Raycast(transform.position, direction);
Vector2 rayDirection = (hit.point - new Vector2( transform.position.x, transform.position.y));
Debug.DrawRay(transform.position, rayDirection);
}
}
}

Related

unity2d move a game object towards a random position

i have a satellite which i let spawn randomly in a different script by just using the method Satellite() and i want it move towards the bottom of the screen but not towards the middle but again a random position of the ground. the problem is that satellitedirection is always 0. also, if i somehow would manage to get the problem solved, wouldn´t every satellite on the screen move towards the same position?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SatelliteBehaviour : MonoBehaviour
{
[SerializeField] Rigidbody2D satelliteRB;
[SerializeField] Transform satelliteFirePoint;
[SerializeField] GameObject satellitePrefab;
float satellitedirection;
void Start()
{
}
void Update()
{
transform.Rotate(0,0,80*Time.deltaTime);
//satelliteRB.velocity = -transform.up * 5;
transform.position = Vector2.MoveTowards(transform.position, new Vector2(satellitedirection, -15), 1 * Time.deltaTime);
Debug.Log(satellitedirection);
}
public void Satellite()
{
Instantiate(satellitePrefab, new Vector2(Random.Range(-18,18),10), Quaternion.identity);
satellitedirection = Random.Range(-18, 18);
}
}
The Instantiate() method returns a game object but it is not assigned to anything. Assign a var and set its position and rotation.
GameObject satelliteObj = Instantiate(satellitePrefab, new Vector2(Random.Range(-18,18),10), Quaternion.identity);
// random rotation
satelliteObj.transform.rotation = Quaternion.Euler(new Vector2(Random.Range(-180, 180), Random.Range(-180, 180)));

3D Isometric game in Unity - Projectile follows player movements

I'm trying to make a 3D Isometric game with a wizard shooting fireballs. I managed to make it shoot the fireball but they go in the direction which the wizard is facing: if I rotate the wizard the fireballs change direction. What can I do? Thanks for helping me.
This is the script I made (attached to the player):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WizardController : Characters
{
[SerializeField]
public Transform spawnMagic;
private GameObject magicShot;
public List<GameObject> magicBullets = new List<GameObject>();
private void Start()
{
maxHP = 150.0f;
magicShot = magicBullets[0];
}
void Update()
{
GetInputs();
Attack();
Defend();
cameraFollow();
}
private void FixedUpdate()
{
LookAt();
Move();
}
public override void Attack()
{
if (Input.GetButtonDown("Fire1"))
{
GameObject magicBullet;
isAttacking = true;
GetComponent<Animator>().SetBool("hit1", true);
if (spawnMagic != null)
{
magicBullet = Instantiate(magicShot, spawnMagic.transform.position, Quaternion.identity);
}
}
else
{
GetComponent<Animator>().SetBool("hit1", false);
}
}
}
The movement script for the bullet is a simple "transform.position" line:
transform.position += spawnMagic.forward * (speed * Time.deltaTime);
And this is what happen when the player shoot:
https://youtu.be/TYwWDr8W4Q4
To solve this problem, you must make the bullet movement independent of the any objects that are Child of wizard or depend on it transfrom.
If you are careful, the spawnMagic rotates as the wizard moves, and the bullet is referenced by spawnMagic.forward.
First you need to place bullet rotation same as spawn spawnMagic rotation during production.
magicBullet = Instantiate(magicShot, spawnMagic.transform.position, spawnMagic.transform.rotation)
Then replace spawnMagic.forward with local bullet forward at movement part, it will make bullet movement indepent of spawnMagic direction during move phase:
transform.position += transform.forward * (speed * Time.deltaTime)

How do I make a camera that points towards where the player is going and is back and up and pointed down?

it is a ball that actally rolls so I can't just put a child camera on with an offset and call it a day so instead I created this script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class camera : MonoBehaviour
{
public GameObject Player;
public Vector3 lastpos;
public Vector3 cameraxyz;
public Vector3 camerarotationxyz;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
Vector3 currentDirection = Player.transform.position - lastpos;
transform.rotation = Quaternion.LookRotation(currentDirection-camerarotationxyz);
transform.position = currentDirection + cameraxyz;
Vector3 lastPos = Player.transform.position;
}
}
and attached it to an empty game object made the game object a child of the ball and then made the camera a child of the empty game object
which half works the empty game object will all always rotate to have it's z axis aligned with the origin meaning the offset for the camera is wrong and it won't look at where the ball is going but will look towards the ball
this is how I set the hierarchy up (I put the script on the empty game object)
https://i.stack.imgur.com/sbiMt.png
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class camera : MonoBehaviour
{
public GameObject Player;
public Vector3 lastPos;
public Vector3 cameraxyz;
public Vector3 camerarotationxyz;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
Vector3 currentDirection = Player.transform.position - lastPos;
transform.rotation = Quaternion.LookRotation(currentDirection - new Vector3(0,currentDirection.y,0));
Vector3 newPosition = currentDirection + cameraxyz;
transform.position = newPosition;
lastPos = Player.transform.position;
transform.position = Player.transform.position;
}
}
taking the Vector3 off of lastPos and capitalizing mistakes leads to a gameobject with an incorrect offset and rotation to stop it traking the y axis (as I can change which whay is up and change the y to be parrallel to gravity using an external script) I did (currentDirection - new Vector3(0,currentDirection.y,0) the new Vector3 is needed and so are the zeros as a float nor int cannot be use to subtract from a Vector3 then I did transform.position = Player.transform.position; so that the empty game object is correctly put on the ball then to get the camera to move with the correct offset I made the camera a child of the emptygameobject

Unity - Aim Line (Line Renderer) not showing in 2D shooter

I'm a Unity novice and I'm creating a small 2D shooting game on a school project and I already managed to have a functional shooting system in the main character that even bounces off some objects using Unity Physics.
I now wanted to integrate an aim line that will predict the trajectory of the bullet, including the bounces on objects (bubble-shooter style).
I found a script that uses Raycast and Line Renderer and it supposedly does this and I tried to integrate it into my gun script but although it does not give any error, it simply does not show anything when I test the game. I do not know if the problem is in the settings that I put in the Line Renderer Component or it is in the Script.
Could someone help me understand where my error is and point the right way?
My goal is:
My Line Renderer Component Definitions:
My Weapon Script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(LineRenderer))]
public class Weapon : MonoBehaviour
{
[Range(1, 5)]
[SerializeField] private int _maxIterations = 3;
[SerializeField] private float _maxDistance = 10f;
public int _count;
public LineRenderer _line;
public Transform Firepoint;
public GameObject BulletPrefab;
public GameObject FirePrefab;
void Start()
{
_line = GetComponent<LineRenderer>();
}
// Update is called once per frame
void Update()
{
if (Input.GetButtonDown("Fire1"))
{
Shoot();
}
_count = 0;
_line.SetVertexCount(1);
_line.SetPosition(0, transform.position);
_line.enabled = RayCast(new Ray(transform.position, transform.forward));
}
void Shoot()
{
//shooting logic
var destroyBullet = Instantiate(BulletPrefab, Firepoint.position, Firepoint.rotation);
Destroy(destroyBullet, 10f);
var destroyFire = Instantiate(FirePrefab, Firepoint.position, Firepoint.rotation);
Destroy(destroyFire, 0.3f);
}
private bool RayCast(Ray ray)
{
RaycastHit hit;
if (Physics.Raycast(ray, out hit, _maxDistance) && _count <= _maxIterations - 1)
{
_count++;
var reflectAngle = Vector3.Reflect(ray.direction, hit.normal);
_line.SetVertexCount(_count + 1);
_line.SetPosition(_count, hit.point);
RayCast(new Ray(hit.point, reflectAngle));
return true;
}
_line.SetVertexCount(_count + 2);
_line.SetPosition(_count + 1, ray.GetPoint(_maxDistance));
return false;
}
}
Unity has two physics engines one for 2D and one for 3D. The script you provided relies on the 3D physics engine and won't work for 2D colliders. I edited your script to function with 2D colliders.
Either way make sure that all your game objects use the same physics system. Also the original script only shows the line renderer if it hits something. Best of luck!
using UnityEngine;
[RequireComponent(typeof(LineRenderer))]
public class Weapon : MonoBehaviour
{
[Range(1, 5)]
[SerializeField] private int _maxIterations = 3;
[SerializeField] private float _maxDistance = 10f;
public int _count;
public LineRenderer _line;
public Transform Firepoint;
public GameObject BulletPrefab;
public GameObject FirePrefab;
private void Start()
{
_line = GetComponent<LineRenderer>();
}
// Update is called once per frame
private void Update()
{
if (Input.GetButtonDown("Fire1"))
{
Shoot();
}
_count = 0;
_line.SetVertexCount(1);
_line.SetPosition(0, transform.position);
_line.enabled = true;
RayCast(transform.position, transform.up);
}
private void Shoot()
{
//shooting logic
var destroyBullet = Instantiate(BulletPrefab, Firepoint.position, Firepoint.rotation);
Destroy(destroyBullet, 10f);
var destroyFire = Instantiate(FirePrefab, Firepoint.position, Firepoint.rotation);
Destroy(destroyFire, 0.3f);
}
private bool RayCast(Vector2 position, Vector2 direction)
{
RaycastHit2D hit = Physics2D.Raycast(position, direction, _maxDistance);
if (hit && _count <= _maxIterations - 1)
{
_count++;
var reflectAngle = Vector2.Reflect(direction, hit.normal);
_line.SetVertexCount(_count + 1);
_line.SetPosition(_count, hit.point);
RayCast(hit.point + reflectAngle, reflectAngle);
return true;
}
if (hit == false)
{
_line.SetVertexCount(_count + 2);
_line.SetPosition(_count + 1, position + direction * _maxDistance);
}
return false;
}
}
Well, I changed on the physics material of the bullet, the Friction to 0 and Bounciness to 1. Also on the rigidbody2D the linear drag, angular drag and gravity scale all to 0. Although it is not a perfect rebound it was very close to what I intend for the game. Thank you! Check it out: Game Gif
Only negative thing is that my bullet is not turning in the direction of the movement after the rebound. I tried to use transform.LookAt but didn`t work. This is my bullet script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bullet : MonoBehaviour
{
public float speed = 20f;
public Rigidbody2D myRigidbody;
// Start is called before the first frame update
void Start()
{
this.myRigidbody = this.GetComponent<Rigidbody2D>();
this.myRigidbody.velocity = transform.right * speed;
transform.LookAt(transform.position + this.myRigidbody.velocity);
}
}
But now i have this error: Error CS0034 Operator '+' is ambiguous on operands of type 'Vector3' and 'Vector2'

Moving gameObject from A to B

I'm trying to animate / transform a gameObject movingObject from it's spawn position to the destination. I believe the issue is somewhere in the implementation of the IncrementPosition function.
Rather than moving the one cube from A to B. The script spawns multiple cubes until it gets to B. Can you see where I'm going wrong?
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class onClickSpawnMove : MonoBehaviour
{
public float speed;
public GameObject randomSpawn;
private GameObject movingObject;
private Vector3 destination;
void Start()
{
Spawn();
}
void Update()
{
SetDestination(movingObject.transform.position);
if (destination != movingObject.transform.position) {
IncrementPosition();
}
}
void IncrementPosition()
{
float delta = speed * Time.deltaTime;
Vector3 currentPosition = movingObject.transform.position;
Vector3 nextPosition = Vector3.MoveTowards(currentPosition, destination, delta);
movingObject.transform.position = nextPosition;
}
void Spawn() {
Vector3 spawnPosition = new Vector3(10, 0, 0);
movingObject = Instantiate(randomSpawn, spawnPosition, Quaternion.identity);
}
public void SetDestination(Vector3 value)
{
destination = new Vector3(20, 0, 0);
}
}
There are several ways to call the Spawn / Start method casually:
gameObject.AddComponent<onClickSpawnMove>(); the Start method will be invoked again.
Instantiate a prefab that onClickSpawnMove script is attached already.
gameObject.SendMessage("Start"); maybe, but rarely seen.
You can add a log or break point to check when the Spawn / Start method is called.
Print the hash code will help you know the different onClickSpawnMove instances.
And you can click the message in the console to know which GameObject is.
void Start()
{
Spawn();
Debug.Log("Start " + this.GetHashCode(), this);
}