Make GameObject "Attached" Right?

This script makes the stick cube all that it comes across. The problem is that when it goes at relatively high or medium speeds (or when the device runs slowly), the cube tends to “go a little” into what it encounters, and then stick to it. What changes should I make to fix this?

For this script to work, one GameObject must have bool _sticksToObjects = true; and the other bool _sticksToObjects = false;

I tried to turn Rigidbody Collision Detection mode into Continuous or Continuous Dynamic

I think my script depends on the frame rate. This may be a problem.

Normal "Attach":

enter image description here

Anomalous "Attach":

enter image description here

 Rigidbody _rigidBody; Transform _meshTransform; bool _sticksToObjects = true; public Transform _stuckTo = null; protected Vector3 _offset = Vector3.zero; void Awake() { GameObject CubeMesh = GameObject.FindWithTag ("CubeMesh"); GameObject Cube = GameObject.FindWithTag ("Cube"); _rigidBody = Cube.GetComponent<Rigidbody> (); _meshTransform = CubeMesh.GetComponent<Transform> (); } void Update() { if (_stuckTo != null) { transform.position = _stuckTo.position - _offset; } } void OnCollisionEnter(Collision collision) { if (!_sticksToObjects) { return; } _rigidBody.isKinematic = true; // Get the approximate collision point and normal, as there // may be multipled collision points Vector3 contactPoint = Vector3.zero; Vector3 contactNormal = Vector3.zero; for (int i = 0; i < collision.contacts.Length; i++) { contactPoint += collision.contacts [i].point; contactNormal += collision.contacts [i].normal; } // Get the final, approximate, point and normal of collision contactPoint /= collision.contacts.Length; contactNormal /= collision.contacts.Length; // Move object to the collision point // This acts as setting the pivot point of the cube mesh to the collision point transform.position = contactPoint; // Adjust the local position of the cube so it is flush with the pivot point Vector3 meshLocalPosition = Vector3.zero; // Move the child so the side is at the collision point. // A x local position of 0 means the child is centered on the parent, // a value of 0.5 means it to the right, and a value of -0.5 means it to the left meshLocalPosition.x = (0.5f * contactNormal.x); _meshTransform.localPosition = meshLocalPosition; if (_stuckTo == null || _stuckTo != collision.gameObject.transform) { _offset = collision.gameObject.transform.position - transform.position; } _stuckTo = collision.gameObject.transform; } 

Here are some screenshots of the Unity editor:

enter image description here

enter image description here

enter image description here

+8
c # unity3d
source share
2 answers

This is a well-known category of problems in gaming technology, and you will be pleased to know that the solution is relatively simple. You will be pleased to hear that there are similar, but much more complex problems that are actually resolved the same way. I'll try to explain.

Now here's the thing. The following question often arises ...

So, I'm working on GTA. I have a humanoid, H running. She approaches car V. She opens the door and sits down and leaves. After that, everything goes to hell in Mekanim, and all the code stops working. What to do?

Surprisingly, the way that is done in games:

Surprisingly: in fact, you exchange for completely different models !!!!!

You have H and V in the game. But then you have an animation (say) to climb H to V. But then you literally destroy the game objects H and V , and you create (or just wake up) a new, completely different, game object , which is D ("car, run by a lady ").

(If you think about it, you can see that when you do this, you carefully adjust all the things in D to match what was “just happening” in the frame, with respect to H and V. So, for example , literally, you copy the transformation, rotation, etc. of car V to a new car inside inside D, if Lady H has SmearedMakeupEffect, you put the same SmearedMakeupEffect on lady -within-D, you put all the bones the same, etc. d.)

Another simple example of this is that you often ask people: "my character C is killed and I want him to become a ragdoll, how?" In fact, you just go to a completely new game object that you have all set up for this walkthrough. Indeed, if you have character A ("Arnie") in the game, it's normal that you have 4 or 5 "different As" sitting off the stage, so there is "ragdoll A", "A that can dance" "A with a weapon." Indeed, many of them are combos, you know "A on the horse", "A in the car", etc.

So interesting, the "real" solution is here,

as soon as they become a new connected thing, destroy them both and replace them with a new game object in general!

if you made the games “until you have a blue face” from the creation of the games, this is exactly what you would do for granted. Although its “a simple situation, it’s just easier in the long run. In the end, consider everything you need to do when this happens:”

  • make the deletion child of another

  • disable physics for child

  • change the way your physics works for all of this.

  • turn off or change the collider on the striking object, possibly making it part of a common object

  • you will most likely have some kind of new physics of "separation", where it can be brought down - you have to turn it all into

  • Most likely, change minor issues such as sound effects, colors, etc.

As you can see, this is a huge task that does all of this, and, indeed, one of those things that it “just does right” and moves on to the new model.


All that has been said, I know that you want a Quick Script Solution that you can paste in :) Here it is ...

Step 0, you will create "YourScript", which will be in the main cube. he will “catch” another cube moving.

YourScript will basically look like this ...

  [System.NonSerialized] public bool isConnectedNow; void OnCollisionEnter(Collision collision) GameObject theThingWeCaught = collision.gameObject Debug.Log("We caught this thing .. " + theThingWeCaught.name) // make it a child of us...... theThingWeCaught.transform.parent = transform theThingWeCaught ... set kinematic theThingWeCaught ... probably disable the rigidbody theThingWeCaught ... probably disable the collider isConnectedNow = true; 

That is really all you need.

Step 1, YOUR Script should have a public bool like this

  [System.NonSerialized] public bool isConnectedNow; 

Step 2, here is the MyScript that goes to the cubic cube, first we check that your isConnectedNow bool is working

 public Class MyScript:MonoBehaviour // attach to the "child" cube { public float correctXDistance; public float correctYDistance; public Transform bigCube; public YourScript yourScript; void Update() { string message = yourScript.isConnectedNow ? "free" : "stuck"; Debug.Log("I am " + message); } } 

attach, debug and run. Make a small cube stick and unfasten it from the large cube. Watch out for the console. it works? So add this to MyScript

 private void DistanceCorrectionX() { float xDistance = bigCube.position.x - transform.position.x; float xSign = Mathf.Sign(xDistance); float xDelta = Mathf.Abs(xDistance); float closenessPercentage = (xDelta/correctXDistance)*100f; if ( closenessPercentage<90f || closenessPercentage>110f) { // they are not close enough to quantize on this axis // this comes in to play when you have multiple axes return; // do nothing. } float xShouldBe = bigCube.position.x + xSign * correctXDistance; Vector3 p = transform; px = xShouldBe; // be careful it .y, .z etc for other axes transform.position = p; } 

for this call in Update () in MyScript like this

  void Update() { Debug.Log("I am " yourScript.isConnectedNow ? "free" : "stuck"); if (yourScript.isConnectedNow) DistanceCorrectionX(); } 

Now actually play and do it. Now that it works in Update simply during playback, look at the Inspector for MyScript and adjust the correctXDistance value to get the exact look you want. When you have defined the value, unPlay and put it as the final value you want.

Next, in DistanceCorrectionX simply duplicate the entire code and do it again for the Y axis of DistanceCorrectionX . If you also execute Z, do it.

At last. Please note that you will have a lot of dirty code, for example ...

  void Update() { // handle all the DistanceCorrectionX etc as seen above. if (yourScript.isConnectedNow) { .. turn off the collider on me } else { .. turn on the collider on me } } 

etc., there are "many little things" you will need to do.

Do not forget also that basically you can make the hit object a child of a large object, depending on your situation. (Then, of course, they will move together as a unit.)

Please note that in the positioning code above, I just showed it as a position, not a local position, for pedagogical clarity. If you want them to expand, rotate, etc., you would make the impact object a child of another, and you would use localPosition in the same way. Enjoy it.

+6
source share

One possible way that comes to my mind:

Inside the “collision enter” check the distance between these objects and move the one that should stick to the other, a little.

As you see in the picture, the distance between A and B should be equal to the sum of the width divided by 2 (with a small threshold, of course). If the distance is less than the sum of the width / 2, then you have an abnormal “attachment” and you have to transfer one of the objects. Its really hard to accomplish.

enter image description here

+1
source share

All Articles