how to visualize the direction of a moving gameobject as a vector in the scene? - unity3d

so I have a moving game object and i want to visualize the direction of its velocity as an arrow ( vector ) ,
I could not find a function that enables me to show that vector in the scene !
Vector3 direction ;
and i'm stuck finding method to show this vector in the scene .

Suppose you're looking for a simple gizmo to visualise the velocity vector. In that case, you could use OnDrawGizmos() to draw it and then enable Gizmos within Game view using the Gizmos toggle located at the right-most of the window:
For the code itself, you could use Handles.ArrowHandleCap to visualise a Rigidbody's velocity as follows:
[RequireComponent(typeof(Rigidbody))]
public class VelocityVisualizer : MonoBehaviour
{
// The length of the arrow, in meters
[SerializeField] [Range(0.5F, 2)] private float arrowLength = 1.0F;
private Rigidbody _rigidbody;
private void Start()
{
_rigidbody = GetComponent<Rigidbody>();
}
private void OnDrawGizmos()
{
if (!Application.isPlaying) return;
var position = transform.position;
var velocity = _rigidbody.velocity;
if (velocity.magnitude < 0.1f) return;
Handles.color = Color.red;
Handles.ArrowHandleCap(0, position, Quaternion.LookRotation(velocity), arrowLength, EventType.Repaint);
}
}
Attach this script as a component of a game object that has a Rigidbody, and it will display its velocity direction using an arrow

Related

Unity3D Clamping cursor to circle to imitate a gamepad joystick

I am working on a 3D, top-down, voxel, spaceship arena shooter (mnk, gamepad) with a static camera.
I am moving the spaceship with WASD and want it to rotate with my mouse input on its Y-axis.
For that, I want to create an invisible circle that stays in the middle of the screen that the cursor can't leave. Based on the position of the cursor in the circle I want to rotate my spaceship independent from where the ship is.
Diagram for clarification
I don't know how to calculate this angle and apply it to the rotation of my ship or even how to create such circle with the limited cursor movement. I want to add a crosshair in the end and I use the new input system (if that's relevant).
So far my code for the movement looks like this:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class MovementBehaviour : MonoBehaviour
{
private Rigidbody sphereRigbod;
private PlayerInput playerInput;
private PlayerInputActions playerInputActions;
private Camera mainCamera;
public WeaponBehaviour weapon;
public Vector3 playerRotation;
[SerializeField] private float speed = 70f;
private void Awake()
{
sphereRigbod = GetComponent<Rigidbody>();
playerInput = GetComponent<PlayerInput>();
playerInputActions = new PlayerInputActions();
playerInputActions.PlayerMovement.Enable(); //Enables EVERY Action map set up!
mainCamera = FindObjectOfType<Camera>();
}
private void FixedUpdate()
{
//X Z Movement WASD
Vector2 inputVector = playerInputActions.PlayerMovement.Movement.ReadValue<Vector2>();
sphereRigbod.AddForce(new Vector3(inputVector.x, 0, inputVector.y) * speed, ForceMode.Force);
}
}
This is what my movement looks like at the moment.
Edit: made this ugly animation for further clarification.

Unity - How to calculate new position for an object from pitch of another object in 3D

I would like to calculate a new position based on the pitch of a mesh in order to make an object following the top of my object which is rotated:
And result in:
I cannot make the square object as represented above as a child (in the Unity object hierarchy) of the line object because the rotated object can see its scale changed at anytime.
Does a mathematics solution can be used in this case?
Hotspots
If you'd like to place something at a particular location on a generic object which can be scaled or transformed anywhere, then a "hotspot" can be particularly useful.
What's a hotspot?
Edit the target gameobject (the line in this case) and add an empty gameobject to it. Give it some appropriate name - "cross arms hotspot" for example, and then move it to the location where you'd like your other gameobject to target. Essentially, a hotspot is just an empty gameobject - a placement marker of sorts.
How do I use it?
All you need is a reference to the hotspot gameobject. You could do this by adding a little script to the pole gameobject which tracks it for you:
public class PowerPole : MonoBehaviour {
public GameObject CrossArmsHotspot; // Set this in the inspector
}
Then you can get that hotspot reference from any power pole instance like this:
var targetHotspot = aPowerPoleGameObject.GetComponent<PowerPole>().CrossArmsHotspot;
Then it's just a case of getting your target object to place itself where that hotspot is, using whichever technique you prefer. If you want it to just "stick" there, then:
void Start(){
targetHotspot = aPowerPoleGameObject.GetComponent<PowerPole>().CrossArmsHotspot;
}
void Update(){
transform.position = targetHotspot.transform.position;
}
would be a (simplfied) example.
A more advanced example using lerp to move towards the hotspot:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CrossArmsMover : MonoBehaviour
{
public GameObject PowerPole;
private GameObject targetHotspot;
public GameObject CrossArms;
public float TimeToTake = 5f;
private float timeSoFar;
private Vector3 startPosition;
private Quaternion startRotation;
// Start is called before the first frame update
void Start()
{
startPosition = CrossArms.transform.position;
startRotation = CrossArms.transform.rotation;
targetHotspot = PowerPole.GetComponent<PowerPole>().CrossArmsHotspot;
}
// Update is called once per frame
void Update()
{
timeSoFar+=Time.deltaTime;
var progress = timeSoFar/TimeToTake;
// Clamp it so it doesn't go above 1.
if(progress > 1f){
progress = 1f;
}
// Target position / rotation is..
var targetPosition = targetHotspot.transform.position;
var targetRotation = targetHotspot.transform.rotation;
// Lerp towards that target transform:
CrossArms.transform.position = Vector3.Lerp(startPosition, targetPosition, progress);
CrossArms.transform.rotation = Quaternion.Lerp(startRotation, targetRotation, progress);
}
}
You would need to put a script on the following gameobject in wich you would put :
GameObject pitcher = //reference to the gameobject with the pitch;
const int DISTANCE_ON_LINE = //distance between the 2 objects
void Update() {
transform.position = pitcher.transform.position + pitcher.transform.forward * DISTANCE_ON_LINE;
}

How do I show the end screen when I touch the enemies in unity

I’m make a 2D game in unity and I searched for a solution but I did not find anything.
This for a new game in unity
using UnityEngine;
public class PlayerMovement : MonoBehaviour
{
public float speed = 6f; // The speed that the player will move at.
Vector3 movement; // The vector to store the direction of the player's movement.
Animator anim; // Reference to the animator component.
Rigidbody playerRigidbody; // Reference to the player's rigidbody.
int floorMask; // A layer mask so that a ray can be cast just at gameobjects on the floor layer.
float camRayLength = 100f; // The length of the ray from the camera into the scene.
void Awake ()
{
// Create a layer mask for the floor layer.
floorMask = LayerMask.GetMask ("Floor");
// Set up references.
anim = GetComponent <Animator> ();
playerRigidbody = GetComponent <Rigidbody> ();
}
void FixedUpdate ()
{
// Store the input axes.
float h = Input.GetAxisRaw ("Horizontal");
float v = Input.GetAxisRaw ("Vertical");
// Move the player around the scene.
Move (h, v);
// Turn the player to face the mouse cursor.
Turning ();
// Animate the player.
Animating (h, v);
}
void Move (float h, float v)
{
// Set the movement vector based on the axis input.
movement.Set (h, 0f, v);
// Normalise the movement vector and make it proportional to the speed per second.
movement = movement.normalized * speed * Time.deltaTime;
// Move the player to it's current position plus the movement.
playerRigidbody.MovePosition (transform.position + movement);
}
void Turning ()
{
// Create a ray from the mouse cursor on screen in the direction of the camera.
Ray camRay = Camera.main.ScreenPointToRay (Input.mousePosition);
// Create a RaycastHit variable to store information about what was hit by the ray.
RaycastHit floorHit;
// Perform the raycast and if it hits something on the floor layer...
if(Physics.Raycast (camRay, out floorHit, camRayLength, floorMask))
{
// Create a vector from the player to the point on the floor the raycast from the mouse hit.
Vector3 playerToMouse = floorHit.point - transform.position;
// Ensure the vector is entirely along the floor plane.
playerToMouse.y = 0f;
// Create a quaternion (rotation) based on looking down the vector from the player to the mouse.
Quaternion newRotation = Quaternion.LookRotation (playerToMouse);
// Set the player's rotation to this new rotation.
playerRigidbody.MoveRotation (newRotation);
}
}
void Animating (float h, float v)
{
// Create a boolean that is true if either of the input axes is non-zero.
bool walking = h != 0f || v != 0f;
// Tell the animator whether or not the player is walking.
anim.SetBool ("IsWalking", walking);
}
I tried some codes up here but it doesn't do what I want in my game. There is no health.
You can use the function OnCollisionEnter2D to check if your player collides with an enemy. This function triggers whenever the GameObject enters the hit box of another GameObject
For example:
void OnCollisionEnter2D(Collision2D other) {
if (other.gameObject.tag == "enemy") {
// Gameover... show end screen
}
}
Just don't forget to set the "tags" on your enemies in the editor.
For more information check out the links below
https://docs.unity3d.com/ScriptReference/MonoBehaviour.OnCollisionEnter2D.html
https://answers.unity.com/questions/1408186/how-to-check-if-boxcollider2d-collided-with-anothe.html
I'am assuming you are a new user to unity, so Iam gonna help you with the code a bit more than I usually do.
to detect a collision with an enemy in 2d, we use the function OnCollisionEnter2d and what it does is basically detects collision in 2d and stores the collision's info into a variable, here is the documentation... please read to understand more.
So after you wrote the OnCollisionEnter2d function, inside it you would need to write an if statement that uses the OnCollisionEnter2d info that is stored in a variable. And checks whether the tag of the other game object is compatible with what you wrote in the code.
then you have to make a function(s) to enable and disable the UI components of your game. Since I don't what are those components, I will not write that code in and I will just write some examples. here is some documentation that might help.
here is the code:
void OnCollisionEnter2d(Collision2d other)
{
if (other.gameObject.tag == "enemy")
{
disableEnableUI();
}
}
here is the disableEnableUI(); function:
public GameObject restartButton;
public GameObject gameOverTxt;
void disableEnableUI()
{
restartButton.SetActive(true);
gameOverTxt.SetActive(true);
}

how to limit and clamp distance between two points in a Line renderer unity2d

I am making a game which let you click on a ball and drag to draw a line renderer with two points and point it to a specific direction and when release I add force to the ball,
for now, I just want to know how can I limit the distance between those two points like give it a radius.
You can simply clamp it using a Mathf.Min.
Since you didn't provide any example code unfortunately here is some example code I made up with a simple plane with a MeshCollider, a child object with the LineRenderer and a camera set to Orthographic. You probably would have to adopt it somehow.
public class Example : MonoBehaviour
{
// adjust in the inspector
public float maxRadius = 2;
private Vector3 startPosition;
[SerializeField] private LineRenderer line;
[SerializeField] private Collider collider;
[SerializeField] private Camera camera;
private void Awake()
{
line.positionCount = 0;
line = GetComponentInChildren<LineRenderer>();
collider = GetComponent<Collider>();
camera = Camera.main;
}
// wherever you dragging starts
private void OnMouseDown()
{
line.positionCount = 2;
startPosition = collider.ClosestPoint(camera.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, transform.position.z)));
var positions = new[] { startPosition, startPosition };
line.SetPositions(positions);
}
// while dragging
private void OnMouseDrag()
{
var currentPosition = GetComponent<Collider>().ClosestPoint(camera.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, transform.position.z)));
// get vector between positions
var difference = currentPosition - startPosition;
// normalize to only get a direction with magnitude = 1
var direction = difference.normalized;
// here you "clamp" use the smaller of either
// the max radius or the magnitude of the difference vector
var distance = Mathf.Min(maxRadius, difference.magnitude);
// and finally apply the end position
var endPosition = startPosition + direction * distance;
line.SetPosition(1, endPosition);
}
}
This is how it could look like
I've written the following pseudo code, which may help you
float rang ;
Bool drag=true;
GameObject ball;
OnMouseDrag () {
if(drag) {
//Put your dragging code here
}
if (ball.transform.position>range)
Drag=false;
else Drage=true;
}

Unity Change UI Z-Axis

I'm creating an Archery, Platformer, Shooting game named "ArcheryRun" with a small team. We have a powerbar (shown in orange) which increases as you hold down the "Left Mouse Button". However since its a UI element it is static in a position.
I would like it to appear above the player when they change their z-axis as Ive done with the Arrow Image by using a 2D Sprite object. However I can't seem how to change the z-axis of a UI Image relative to the player or use a Game Object which allows a fill option.
Any help is appreciated, thanks :)
Change Orange Powerbar to Follow Player
If we understand your question, this should work:
This method gives you screen canvas position from world position:
public static Vector3 GetScreenPositionFromWorldPosition(Vector3 targetPosition)
{
Vector3 screenPos;
screenPos = Camera.main.WorldToScreenPoint(targetPosition);
return new Vector3 (screenPos.x, screenPos.y, 0f);
}
Then you need a script on top of power bar, lets say like this:
public class PowerBar : MonoBehaviour
{
public Transform target;
RectTransform _rectTransform;
void Awake ()
{
_rectTransform = GetComponent<RectTransform> ();
}
public void updatePosition()
{
Vector3 pos = YourStaticClassWith.GetScreenPositionFromWorldPosition (target.position);
Vector2 rpos = pos;
_rectTransform.anchoredPosition3D = rpos + Vector2.up * 100f; // 100f is value of how many pixels above the target that UI element should apear
}
void LateUpdate()
{
updatePosition ();
}
}
The target is basicly transform of your player object.
The 100f value represents pixels above the target.