Unity3D RigidBody MovePosition Flicker - c#

I currently am working on a game where I am using click to move in Unity. When I click on a spot on the map, I set that mouse's click to the destination and then use the rigidBody on the gameobject to move it using RigidBody.MovePosition(). When I do this, I am getting a lot of flicker when the gameobject reaches its destination. Any assistance is appreciated. Thanks.
// COMPONENTS
Rigidbody rigidBody;
// MOVEMENT
Vector3 destination;
Vector3 direction;
// Use this for initialization
void Start()
{
rigidBody = GetComponent<Rigidbody>();
destination = transform.position;
}
// Update is called once per frame
void Update()
{
DetectInput();
}
void FixedUpdate()
{
MoveControlledPlayer();
}
void MoveControlledPlayer()
{
transform.LookAt(destination);
Vector3 direction = (destination - transform.position).normalized;
rigidBody.MovePosition(transform.position + direction * 5 * Time.deltaTime);
}
void DetectInput()
{
if (Input.GetMouseButton(0))
{
SetDestination();
}
}
void SetDestination()
{
if (!EventSystem.current.IsPointerOverGameObject())
{
Plane field = new Plane(Vector3.up, transform.position);
Ray ray;
float point = 0;
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (field.Raycast(ray, out point))
destination = ray.GetPoint(point);
}
}

I do these kind of movements with temporary joints. They are extremely accurate / configurable / embeddable.
In 2D I use a DistanceJoint2D to control distance between rigidbody points, or between a body and a world point. In 3D you could use SpringJoint or ConfigurableJoint.
Then just tween the distance basically the same way you do per frame moving now (on FixedUpdate).

Reaching a point when using a velocity-based behavior is really hard, and often results in flickering: that's because the object is always passing over his destination.
A way to fix it is to stop the movement when the object is close enought to the target.

Related

How do I make a game object follow my mouse position with a rigidbody2D?

I started a new game project, and I have tried to find a way to only use a rigidbody2D component to move my player game object instead of using transform.position. And I can't come up with a good way to do it or find a tutorial or documentation about it.
I have got it to work with transform.position, but how could I do it with rigidbody2D?
For movement with RigidBody2D you have mutiple options which are physics based.
I assume that's the reason you want to use RigidBody2D in the first place.
RigidBody2D obj = GetComponent();
private void moveBody()
{
//direction towards your goal
Vector2D v = mousePosition - transform.position;
//Example 1 set the velocity
obj.velocity = v;
//Example 2 apply force
obj.AddForce(v, ForceMode2D.Impulse);
}
you can read more about RigidBody2D movement
here
You can throw an invisible collider on your stage and move your object to the position you want with the ray.
Ray ray;
public RaycastHit hit;
private void Update()
{
ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit, 100f))
{
Debug.DrawRay(Camera.main.transform.position,hit.point);
transform.position = hit.point;
}
}
Best.

GameObject.FindGameObjectWithTag isn't detecting cloned objects

I have a script that moves instantiated game objects depending on their tag. However, the game objects that have been instantiated are not moving.
Instantiation Script:
void Update()
{
tillNextSpawn += Time.deltaTime;
Debug.Log(tillNextSpawn);
if (tillNextSpawn >= 2)
{
UnityEngine.Debug.Log("Instantiating circle");
screenPosition = Camera.main.ScreenToWorldPoint(new Vector3(Random.Range(0, Screen.width), Random.Range(0, Screen.height), Camera.main.farClipPlane / 2));
Instantiate(circle, screenPosition, Quaternion.identity);
tillNextSpawn = 0.0f;
}
}
Enemy controller script(moves the enemies)
void FixedUpdate()
{
/*GameObject[]*/
var objects = GameObject.FindGameObjectsWithTag("Enemy");
var objectCount = objects.Length;
foreach (var obj in objects)
{
// Move the players accordingly
var rb = obj.GetComponent<Rigidbody2D>();
Debug.Log(rb);
Vector2 direction = (player.position - obj.transform.position).normalized;
rb.velocity = direction * moveSpeed;
}
}
You should be able to that, and the issue maybe somewhere else in your project.
I created a sample project that recreates what you're trying to do, trying to be as similar as I could be to the sample code you send, you can find it here:
https://github.com/webocs/unity-so-sample-tags
For what I can see, your console is sending an exception
get_main is not allowed to be called...
What comes to my mind, is that that exception is breaking the entire execution, and that's why nothing is happening.
As a side note, I don't know your project so I don't really know why you're building it this way. Said that, why aren't you creating an Enemy script that's attached to the enemy prefab? If you have many enemies you're going to be finding and iterating through all of them in each update tic. If you create an Enemy script and attach it to the prefab you should be able to handle the movement of the enemy using the transform of the gameObject that the script is attached to. This way each enemy is a standalone entity.
I hope all of this helps!
Edit:
I've edited the repo and added a scene called "IndividualEnemies" that illustrates what I told you in the comments
If you want the enemy to follow the player, try doing the following:
//Attach this script to the enemy
Transform player;
private Rigidbody2D rb;
private Vector2 movement;
public float moveSpeed;
void Awake()
{
player = ScriptNameOnPlayer.instance.gameObject.transform;
}
// Start is called before the first frame update
void Start()
{
rb = this.GetComponent<Rigidbody2D>();
}
void Update()
{
Vector3 direction = player.position - transform.position;
direction.Normalize();
movement = direction;
}
void FixedUpdate()
{
moveCharacter(movement);
}
void moveCharacter(Vector2 direction)
{
rb.MovePosition((Vector2)transform.position + (direction * moveSpeed * Time.deltaTime));
}
//But make sure your player script has this line of code:
public static ScriptNameOnPlayer instance;
Hope this helps !

Projectile not shooting direction of my weapon

So my game is sort of like a 3d top down shooter, so I want my gun to shoot wherever the mouse is and it wont go to the mouse unless im shooting down. If you've seen brackyes game called ball wars, im sort of trying to replicate one like that but the projectile is not shooting the right way.
I got my script from blackthornprods ranged combat tutorial (which is for 2d so maybe thats the issue but I dont know how to solve it) :
public float speed;
public float lifeTime;
private void Start()
{
Invoke("DestoryProjectile", lifeTime);
}
private void Update()
{
transform.Translate(transform.up * speed * Time.deltaTime);
}
void DestroyProjectile()
{
Destroy(gameObject);
}
Appreciate anyone to try!
Here is my other script:
Camera mainCam;
public GameObject projectile;
public Transform shotPoint;
private float timeBtwShots;
public float startTimeBtwShots;
void Awake()
{
mainCam = Camera.main;
}
void Update()
{
float objectDepthFromCamera = Vector3.Dot(
transform.position - mainCam.transform.position,
mainCam.transform.forward);
Vector3 cursorWorldPosition = mainCam.ScreenToWorldPoint(Input.mousePosition
+ Vector3.forward * objectDepthFromCamera);
Vector3 localUpNeeded = Vector3.Cross(Vector3.forward,
cursorWorldPosition - transform.position);
transform.rotation = Quaternion.LookRotation(Vector3.forward, localUpNeeded);
if(timeBtwShots <= 0)
{
if (Input.GetMouseButtonDown(0))
{
Instantiate(projectile, shotPoint.position, transform.rotation);
timeBtwShots = startTimeBtwShots;
}
}
else
{
timeBtwShots -= Time.deltaTime;
}
}
Projectile not shooting direction of my weapon. Simple solution -
First instantiate or pool the instance of projectile.
Set rotation of projection from the rotation of weapon & set location to spawn point
Now fire, or whatever strategy you are using
Consider Global rotation, if you need help, tell me, I will edit and give a snippet of code.
This should work. If doesn't post all necessary code, I will give a better solution.
Here is sample github project I created, just for you. I opened Unity nearly after a year. Please check all the versions.
Must check :
firing in facing direction 💋
just instantiate at spawn point
just added some rotation
I think this should give you concept.
Press X for a rantom rotation
Press Space to shoot a projectile :lol:
The white cube shows that it always shoots at a constant direction

How to AddTorque towards an object

I have two cubes. One of them must rotate towards the other one all the time. The things is that the other cube always changes its position. Here is an image that explains what i need.
I tried to AddTorque to the direction between them but it did not work.
transform.GetComponent<Rigidbody>().AddTorque(transform.position - OtherCube.transform.position * 10f * Time.smoothDeltaTime);
Any help appreciated!
EDIT:
The rotating cube's face not always looking to other cube so it should rotate without looking to the other cube. (I meant it should rotate from closest face or edge or anywhere. does not matter).
You can use a cross product to find the axis you're interested in, taking into account the direction of the ground:
private Rigidbody rb;
void Start() { rb = GetComponent<Rigidbody>(); } // cache results of GetComponent
void TurnTowards()
{
Vector3 groundDirection = Vector3.down;
Vector3 towardsOther = (OtherCube.transform.position - transform.position).normalized;
Vector3 rotateAxis = Vector3.Cross(towardsOther, groundDirection);
float rotateMagnitude = 500f; // tune as necessary
rb.AddTorque(rotateMagnitude * Time.smoothDeltaTime * rotateAxis);
}
I think it is easier if you use an empty object as the father of the cube, freezing movement in the cube.
With that, you can make the parent just LookAt the other cube, and the cube just AddTorque on his X axis, the code will be simple like this:
private Transform parent;
private Rigidbody rb;
void Start() {
parent = transform.parent;
rb = GetComponent<Rigidbody>();
}
void Update()
{
Quaternion rot = transform.rotation;
parent.LookAt(otherCube.transform);
transform.rotation = rot;
rb.AddTorque(rotateMagnitude * parent.right);
}

Following instruction for drag and drop 3d object unity but not working

Hi so i have followed every instruction from youtube videos (https://m.youtube.com/watch?v=NMt6Ibxa_XQ) but in the game mode i still cant drag and drop my cube, the cube just stay still when i click and drag it. This problem really gave me a headache i’m pretty sure i have followed every detail from the video and repeat it over and over, thank’s for your time and help i really appreciate and need it, thank youi
in order for your cube to take the OnMouseDown() event you need to add a collider and rigidbody. click the cube, go to the properties on the right and click
add component - physics - cube collider
then do the same, for the rigid body
add component - physics - rigid body.
dont forget to set the rigidbody to kinematic, or set the gravity scale to 0 if you dont want it to fall out of the scene
use this script in order to drad and drop 3D Objects :
using UnityEngine;
using System.Collections;
public class DragAndDrop : MonoBehaviour
{
private bool _mouseState;
private GameObject target;
public Vector3 screenSpace;
public Vector3 offset;
// Use this for initialization
void Start ()
{
}
// Update is called once per frame
void Update ()
{
// Debug.Log(_mouseState);
if (Input.GetMouseButtonDown (0)) {
RaycastHit hitInfo;
target = GetClickedObject (out hitInfo);
if (target != null) {
_mouseState = true;
screenSpace = Camera.main.WorldToScreenPoint (target.transform.position);
offset = target.transform.position - Camera.main.ScreenToWorldPoint (new Vector3 (Input.mousePosition.x, Input.mousePosition.y, screenSpace.z));
}
}
if (Input.GetMouseButtonUp (0)) {
_mouseState = false;
}
if (_mouseState) {
//keep track of the mouse position
var curScreenSpace = new Vector3 (Input.mousePosition.x, Input.mousePosition.y, screenSpace.z);
//convert the screen mouse position to world point and adjust with offset
var curPosition = Camera.main.ScreenToWorldPoint (curScreenSpace) + offset;
//update the position of the object in the world
target.transform.position = curPosition;
}
}
GameObject GetClickedObject (out RaycastHit hit)
{
GameObject target = null;
Ray ray = Camera.main.ScreenPointToRay (Input.mousePosition);
if (Physics.Raycast (ray.origin, ray.direction * 10, out hit)) {
target = hit.collider.gameObject;
}
return target;
}
}

Categories

Resources