Controlling two GameObjects without them affecting eachother
Hello guys, I am kinda new to Unity (working in Unity for 5weeks). I am trying to make simple Hockey game where I control my own character and puck. I didn't got really far, I have so far right click movement via NavMeshAgent, Hockey rink etc. What Im trying to achieve is: 1) Player that is spawned is spawning without puck with stick (I got this one done) 2)When he moves or more likely collides with puck, then puck follows the blade of stick which is puck handling / control - I kinda have this one done aswell 3) When Player press left click mouse button, puck is getting shot / moved towards the left click position
Code is here: using System.Collections; using System.Collections.Generic; using UnityEngine;
public class ParentChildrenScript : MonoBehaviour
{
public GameObject mPlayer;
public GameObject mtPuck;
public bool playerHitsAPuck = false;
public Rigidbody mPuck;
public Rigidbody mrbPlayer;
public LayerMask whatCanBeClickedOn;
public int shotForce = 100;
void OnCollisionEnter(Collision collidingWith)
{
if (collidingWith.collider.name == "Puck")
{
//mrbPlayer.isKinematic = true;
//mPuck.isKinematic = true;
Debug.Log("Player just hit a puck");
playerHitsAPuck = true;
Debug.Log(playerHitsAPuck);
}
}
void Update()
{
if (playerHitsAPuck)
{
Debug.Log(playerHitsAPuck);
mtPuck.transform.parent = mPlayer.transform;
}
if (Input.GetMouseButtonDown(0) && playerHitsAPuck)
{
Vector3 mousePosition = Input.mousePosition;
Ray castPoint = Camera.main.ScreenPointToRay(mousePosition);
RaycastHit hit;
if (Physics.Raycast(castPoint, out hit, Mathf.Infinity, whatCanBeClickedOn))
{
//mPuck.AddForce(hit.point * shotForce);
mPuck.velocity = new Vector3(shotForce, 0, 0);
playerHitsAPuck = false;
//mrbPlayer.isKinematic = false;
//mPuck.isKinematic = false;
mPlayer.transform.DetachChildren();
}
}
}
}
My problem is clear: When player hits a puck then puck starts following however the puck is starting to act really weirdly while player is moving different positions etc. And most of the time just teleports away into insane coordinates or fall through ground or walls. I guess its caused because of Rigidbodies on Puck and Player, but I have no idea how to make it act smoothly. My goal is to reach point where I can do like self passes, dribbles shots on goal and so on. I hope you guys able to help a noob, I wish you all nice summer day! Simon
Answer by Okido · Aug 02, 2019 at 08:08 PM
Hi Simon, the strange behaviour you're seeing appears to be because you're making a rigidbody object a child of another rigidbody object. This will mean all forces applies to the parent will be applied to the child, and additionally all forces applied to the child are still applied, and it always results in really strange looking behaviour.
You can avoid it by setting the object to kinematic/turning off gravity, then setting the parent (when you're "picking" up the object). When it's time to launch the puck, remove the parent, then set it to use gravity/no longer be kinematic.
Also in this code it looks like line 48 (mPlayer.transform.DetachChildren();) will never be read, because its inside an if statement that requires playerHitsAPuck to be true, and you set that to false on line 45 (this will cause the code to immediately back out of that if statement).
Answer by unity_-v4z-HsChKdEYQ · Aug 03, 2019 at 05:49 PM
@Okido is right.. i can make another suggestion .. unity physics are hard to calibrate just right.. so tale your time in adjusting the rigidbody component values to get the results you need. a suggestion to improve the code: try using a coroutine to detach the puck and then perform all the physics actions needed. this makes sure the puck is independent from your player before any forces are applied.
//set a check bool for the couroutine with all other variables and set true when needed.
if (Physics.Raycast(castPoint, out hit, Mathf.Infinity, whatCanBeClickedOn) && boo_to_check_coroutine == true)
{
start coroutine((puck_detachment));
}
IE Enumerator puck_detachment()
{ mPlayer.transform.DetachChildren();
yield return new waitforseconds(float)
//mPuck.AddForce(hit.point * shotForce);
mPuck.velocity = new Vector3(shotForce, 0, 0);
playerHitsAPuck = false;
//mrbPlayer.isKinematic = false;
//mPuck.isKinematic = false;
stop coroutine();
}
dont copy this straight! lot of syntax errors, but an idea. try it.. let me know what happens.