Unity, MoveTowards works weird - c#

Allright, I have gameObjects with tag "Enemy" and I collect them like this:
enemies = GameObject.FindGameObjectsWithTag("Enemy");
After that, I am trying to move the first "Enemy":
int newPositionX;
int newPositionY;
bool targetReached = false;
int moveSpeed = 1;
void Update()
{
if (!targetReached)
{
newPositionX = Mathf.FloorToInt(enemies[0].transform.position.x)-1;
newPositionY = Mathf.FloorToInt(enemies[0].transform.position.y);
enemies[0].transform.position = Vector3.MoveTowards(enemies[0].transform.position,
new Vector3(newPositionX, newPositionY), moveSpeed * Time.deltaTime);
targetReached = true;
}
if (Vector3.Distance(enemies[0].transform.position, new Vector3(
newPositionX, newPositionY)) < 0.1f)
{
targetReached = false;
}
}
But an "Enemy" is not making any moves. I can edit that if I remove the:
targetReached = true;
the "Enemy" is moving but there's no way I can stop it. That makes me think that to make sth moving MoveTowards function should be called permanently in the Update?

MoveTowards returns a vector that moves the gameobject one step in the direction of the target.
Also, I am not sure about this, but looking at your code, the if statement that sets the targetReached to false only runs if the targetReached is already false, so you may want to put that out of the if (!targetReached) statement

You probably had the idea that Unity is a complete game engine.
It isn't.
The most basic of things, like tweening and movement aren't provided in the ways just about every other game engine on earth provides them.
So you need to download and setup a plugins and add-ons to get basic functionality.
Search for tweening engines for Unity, and read up about them, as you'll need to understand them and how they incorporate themselves into Unity for the next time you meet missing basics of Unity.

Related

Unity 2D platform game Dashing using inputSystem

I am making a 2D platform game similar to Megaman X/Zero with unity as my side project, and I am trying to implement the dash function.
Following a course on Udemy, now I can make the Player jump,run and shoot bullets, but I can't make it dash.
I used InputSystem to make moves, here is my code:
void OnJump(InputValue value) //OnJump() is automatically recognized by unity, which will run when the jump button was pressed
{
//if it is pressed and also the capsulecollider of the player is touching Groundlayer(is on ground)
//then add velocity to y so it can jump ONCE
if (value.isPressed && myCapsuleCollider.IsTouchingLayers(LayerMask.GetMask("Ground")))
{
myRigid.velocity += new Vector2(0f,jumpSpeed);
}
}
void OnDash(InputValue value)
{
if (value.isPressed)
{
myRigid.velocity += new Vector2(dashSpeed,0f );
}
}
The way I am thinking is: If I can successfully make the player Jump by adding velocity on y-axis, why can't I make it dash using the same way? just add velocity towards another direction?
Jumping works because the rigid body will take care of gravity and apply it for you, resulting in the character falling down, dashing is different, there is no opposite force to decrease the velocity and therefore your character will only speed up when you try dashing.
The correct implementation should disable input when dashing and to revert the added velocity when it's done.
You can implement that best using a coroutine.
The example below applies a speed boost temporarily, it does not disable the input tho:
private bool isDashing = false;
IEnumerator DashCoroutine(int dashDuration)
{
if(isDashing)
yield break;
isDashing = true;
myRigid.velocity = new Vector(dashSpeed,0);
yield return new WaitForSeconds(dashDuration);
myRigid.velocity = new Vector(0,0);
isDashing = false;
}

Physics2D.OverlapCircleAll not detecting other gameobjects

I have a prefab of a enemy that will spawn in a random position multiple times around the player. However, sometimes this can make one enemy prefab overlap another enemy prefab.
So, I wrote a script which uses Physics2D.OverlapCircleAll() to detect any colliders before instantiating the enemy prefab which avoids the enemy prefab from overlaping an existing enemy. My issue is that the OverlapCircleAll() didn't detect the other instances of the prefab.
I already tried with Physics2D.OverlapBoxAll aswell. If I spawn more than 30 of these "enemy prefabs", at least one will overlap another enemy
This is the code used to detect overlap:
public void SpawnEachEnemy(GameObject Enemy)
{
Vector3 futurePosition = new Vector2(UnityEngine.Random.Range(UpperLeft.transform.position.x, DownRight.transform.position.x),
UnityEngine.Random.Range(UpperLeft.transform.position.y, DownRight.transform.position.y));
bool correctPosition = false;
while (!correctPosition)
{
Collider2D[] collider2Ds = Physics2D.OverlapCircleAll(futurePosition,0.2f);
if (collider2Ds.Length > 0)
{
//re-spawning to prevent overlap
futurePosition = new Vector2(UnityEngine.Random.Range(UpperLeft.transform.position.x, DownRight.transform.position.x),
UnityEngine.Random.Range(UpperLeft.transform.position.y, DownRight.transform.position.y));
}
else
{
correctPosition = true;
}
}
GameObject b = Instantiate(Enemy) as GameObject;
b.transform.position = futurePosition;
b.transform.parent = this.transform;
}
Louis Garczynski mentioned a few of the possibilities but one that wasn't mentioned is that if these are all instantiating in the span of a single frame (a guess based on a comment saying SpawnEachEnemy is called in a loop), then you may need to enable Auto Sync Transforms under Physics2D Settings:
This minimal reproducible example when attached to the camera in a new 3D project's scene should work as you intend with Auto Sync Transforms enabled and it will fail to prevent overlaps when it is disabled. It may be what is preventing it from working for you:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestScript : MonoBehaviour
{
Vector3 upperLeft;
Vector3 downRight;
GameObject prefab;
// Start is called before the first frame update
void Start()
{
transform.position = new Vector3(0, 0, -3);
upperLeft = new Vector3(-1, -1);
downRight = new Vector3(1, 1);
prefab = GameObject.CreatePrimitive(PrimitiveType.Sphere);
DestroyImmediate(prefab.GetComponent<SphereCollider>());
prefab.transform.localScale = 0.4f * Vector3.one;
prefab.AddComponent<CircleCollider2D>();
for (int i = 0; i < 12; i++)
{
SpawnEachEnemy(prefab);
}
prefab.SetActive(false);
}
public void SpawnEachEnemy(GameObject Enemy)
{
Vector3 futurePosition;
Collider2D[] collider2Ds;
do {
futurePosition = new Vector2(
UnityEngine.Random.Range(
upperLeft.x,
downRight.x),
UnityEngine.Random.Range(
upperLeft.y,
downRight.y));
collider2Ds = Physics2D.OverlapCircleAll(futurePosition, 0.2f)
}
while (collider2Ds.Length > 0)
GameObject b = Instantiate(Enemy) as GameObject;
b.transform.position = futurePosition;
b.transform.parent = this.transform;
}
}
I ran into exactly this while writing some feature tests.
As addendum to Ruzihm's awesome answer (was stuck for ages until I found that!).
If your game does not explicitly need AutoSyncTransforms every frame, then its preferable to leave it off, as it can cause a performance hit.
You should only set autoSyncTransforms to true for physics backwards compatibility in existing projects
If you just need it in tests or on a loading frame then:
You can manually call a transform sync with:
Physics.SyncTransforms(); or Physics2D.SyncTransforms();
Or set Physics.autoSyncTransforms = true; at the start, and then back to false at the end of your Start() method.
Either of these is preferable as you don't incur a penalty on subsequent frames.
If your finding you must use AutoSyncTransform or SyncTransform() in normal running. Consider a Coroutine to defer instantiations so that a script isn't creating lots of things at once.
Ideally you want as many frames a second as possible, so there 'may' be little gameplay impact spawning things one/a few at a time, on sequential frames. Rather than incurring an overall performance hit and potential stuttering as a script tries to create too much at once.
First your code could be simplified to something like this:
public void SpawnEachEnemy(GameObject Enemy)
{
Vector3 futurePosition;
do
{
futurePosition = new Vector2(
UnityEngine.Random.Range(UpperLeft.transform.position.x, DownRight.transform.position.x),
UnityEngine.Random.Range(UpperLeft.transform.position.y, DownRight.transform.position.y)
);
} while (Physics2D.OverlapCircleAll(futurePosition,0.2f).Length > 0)
GameObject b = Instantiate(Enemy) as GameObject;
b.transform.position = futurePosition;
b.transform.parent = this.transform;
}
I would also recommend adding a safety counter to your loop, to avoid an infinite loop if there is no room to be found.
Now, a lot of things could be wrong:
Maybe the OverlapCircle and the spawn don't happen in the same place? While setting the parent won't modify the world position, I would still set the position after setting the parent. Not the issue here.
Maybe the size of the overlap is too small ? Are you sure your enemies are 0.2 units in radius? Consider using Debug.DrawLine to draw the radius of the scanned circle.
Maybe your enemies are in a layer not in the DefaultRaycastLayers ? Try using a much larger circle radius and add a Debug.Log whenever OverlapCircleAll actually works.
There are a few other possible reasons, like disabled colliders, or colliders that are too small, etc. This should however cover most likely mistakes.
Thank you, Ruzihm!
I was looking for this answer for days, I had the same problem with my code using Physics2D.OverlapCircle. I am surprised I didn't find anyone who mentions Auto Sync Transforms anywhere else.
if ( Physics2D.OverlapCircle(position, radio) == null) {
GameObject obstacleInst = Instantiate(obstacle, transform);
obstacleInst.transform.position = position;
obstacleInst.transform.localScale = new Vector3(scale, scale, 1);
obstacleInst.transform.rotation = Quaternion.Euler(new Vector3(0, 0, Random.Range(0, 360)));
}

Slow collision detection at low frame rates

I'm experiencing an odd issue with my collision detection. I'm using the Update method to move the player (I don't want to use FixedUpdate because that creates an undesired weird movement). The fixed timestep is set at the default 0.02 (I tried playing with time setting but that didn't work either) . I set the collision detection of the rigidbodies of both objects to "continuous dynamic". Also, I set the target frame rate to 300 and that didn't change anything...
When the framerate is low or the device itself is slow, the collision detection doesn't always work. The player can easily fall through the object it's supposed to collide with, though sometimes it doesn't.
Please tell me what I can do to fix this because I've published a game and many users are reporting this (serious) bug. Thank you for your support.
This is what is supposed to happen:
This is what actually happens:
(as you can see, the cube gets out of the wall and to the other side)
I move the player when the user releases the mouse button:
Script 1:
public Script2 Jumper;
public float TimeToJump;
public void Update()
{
if (Input.GetMouseButtonUp(0))
{
StartCoroutine (Delay (1f/50f)); //Don't mind the time.
}
}
IEnumerator Delay(float waitTime)
{
yield return new WaitForSeconds (waitTime);
if (Jumper != null)
{
Jumper.SetVelocityToJump (gameObject, TimeToJump);
}
}
Script 2 attached to player (cube):
public class Script2 : MonoBehaviour {
GameObject target;
private float timeToJump;
public bool isJumping = false;
public void SetVelocityToJump(GameObject goToJumpTo, float timeToJump)
{
StartCoroutine(jumpAndFollow(goToJumpTo, timeToJump));
this.timeToJump = timeToJump;
this.target = goToJumpTo;
}
private IEnumerator jumpAndFollow(GameObject goToJumpTo, float timeToJump)
{
var startPosition = transform.position;
var targetTransform = goToJumpTo.transform;
var lastTargetPosition = targetTransform.position;
var initialVelocity = getInitialVelocity(lastTargetPosition - startPosition, timeToJump);
var progress = 0f;
while (progress < timeToJump)
{
progress += Time.deltaTime;
if (targetTransform.position != lastTargetPosition)
{
lastTargetPosition = targetTransform.position;
initialVelocity = getInitialVelocity(lastTargetPosition - startPosition, timeToJump);
}
float percentage = progress * 100 / timeToJump;
GetComponent<Rigidbody>().isKinematic = percentage < 100.0f;
transform.position = startPosition + (progress * initialVelocity) + (0.5f * Mathf.Pow(progress, 2) * _gravity);
yield return null;
}
OnFinishJump (goToJumpTo, timeToJump);
}
private void OnFinishJump(GameObject target, float timeToJump)
{
if (stillJumping)
{
this.isJumping = false;
}
}
private Vector3 getInitialVelocity(Vector3 toTarget, float timeToJump)
{
return (toTarget - (0.5f * Mathf.Pow(timeToJump, 2) * _gravity)) / timeToJump;
}
}
The target of the cube is a child of the bigger cube (the wall).
If you require clarification, please leave a comment below. I might give the link to my game if you need more details.
Quote from here (found thanks to #Logman): "The problem exists even if you use continuous dynamic collision detection because fast moving objects can move so fast that they are too far apart from itself from one frame to the next immediate frame. It's like they teleported and no collision detection would ever be triggered because no collision existed, from each frame perspective, and thus from all calculations processed."
In my case, the cube is not going fast, but you get the concept.
There are several issues with your code.
You are asking a Coroutine to yield for 1/50th of a second. The minimum time a yield must occur for is one frame. If Time.deltaTime > 0.02f this is already one of the problems.
You are using Coroutines and yield return null to compute physics calculations. Essentially, you're computing physics in Update(), which is only called once per frame (null is equivalent to new WaitForEndOfFrame(): as mentioned in (1), a running Coroutine cannot be yielding between frames). Under low frame-rate, the amount of motion an object undertook between two frames might exceed the collision range of the target trigger. Assuming linear, non-accelerating motion: ∆S = v∆t where v = velocity, ∆S is movement to cover in the current frame, ∆t is Time.deltaTime. As you can see, ∆S scales proportionally with ∆t.
You have GetComponent<T>() calls inside loops. Always avoid doing this: store a reference as a member variable instead (initialise it in Start()).
My suggestion for the quickest working hack would be to not worry too much about "being clean", and instead create subroutines that you call from FixedUpdate(), and (create and) use member bools to conditionally test which subroutine to "execute" and which to "skip". You can also use member bools or enums as triggers to switch between various "states".
A better solution would be to let Unity handle the kinematics and you instead work with rigidbody mutators (and not transform.positions), but that may be totally unnecessary for an arcade situation, which yours might be. In that case stick to the hack above.
If you really want to control kinematics by hand, use an engine like SFML. A Particle System tutorial would be a good place to start.
It's your float percentage, among other things.
"If isKinematic is enabled, Forces, collisions or joints will not affect the rigidbody anymore."
That's from the isKinematic page of Unity's documentation. You're setting it to true when progress hits 100. So at lower framerates, there'll be a sudden jump due to Time.deltaTime steps being a lot higher, progress is suddenly >= 100, isKinematic is set to true and the player is no longer affected by collisions.
I think you're going to have to rethink a lot of the code here and do some heavy optimisations. But the other posters have laid those out already, so I don't need to.
EDIT: Misunderstood the initial question, thought that it meant you were trying to detect collisions but your code wasn't always detecting them. Didn't realise it actually meant getting the collisions to occur in the first place.

Moving a cardboard around

Quick disclaimer: I am not a very advanced C# user, being more accustomed to languages like python, so i apologise if the answer is right in front of me.
I've been making a little game for the Google Cardboard, Using the demo scene as a base. I've got some code that checks for a "Trigger Pull" and then should translate the Cardboard cameras up by 10 units.
//Checks For Magnet Trigger
if (Cardboard.SDK.Triggered)
{
//moves player up at a rate of 10u/s
transform.Translate(Vector3.up * 10);
Debug.Log("Triggered_Head");
//Tell Cardboard to maintain new position
}
Currently this works really well for detecting the magnet pull, and it does translate the cardboard. The problem is that almost immediately after translation the cardboard gets teleported back to the base position.
Currently i have this code inserted into the UpdateHead() method (?) from CardboardHead.cs, like so:
// Compute new head pose.
private void UpdateHead() {
if (updated) { // Only one update per frame, please.
return;
}
updated = true;
Cardboard.SDK.UpdateState();
if (trackRotation) {
var rot = Cardboard.SDK.HeadPose.Orientation;
if (target == null) {
transform.localRotation = rot;
} else {
transform.rotation = target.rotation * rot;
}
}
if (trackPosition) {
Vector3 pos = Cardboard.SDK.HeadPose.Position;
if (target == null) {
transform.localPosition = pos;
}
else {
transform.position = target.position + target.rotation * pos;
}
//Checks For Magnet Trigger
if (Cardboard.SDK.Triggered)
{
//moves player up at a rate of 10u/s
transform.Translate(Vector3.up * 10);
Debug.Log("Triggered_Head");
//Tell Cardboard to maintain new position
}
}
if (OnHeadUpdated != null) {
OnHeadUpdated(gameObject);
}
}
Doing this does everything right, but the location is reverted almost instantly (in the next frame i assume). So my question is: How do i make the transform stick, and is there a better way for me to handle this?
Alright, i figured out how to handle movement, and I'm posting the solution here for anyone in the future who can't figure it out. Quick note: I did update to the latest version of the SDK, although that shouldn't make a difference, except for naming.
So, Step 1:
Create an object to use as your controller. I just used one of the prototyping cubes from an asset pack, but whatever will work (empty objects would be best).
Place this object more or less in the center-point of the two cameras.
Parent your GvrMain object to the controller object (by dragging it onto the controller object) as well as any other components you want to move with the player (Guns, GUI's, etc)
Step 2:
Create a script for the controller object.
In the Update() method, add the lines:
if (GvrViewer.Instance.Triggered)
{
transform.Translate(Vector3.up)
}
for older versions replace GvrViewer.Instance with Cardboard.SDK
Customise your movement to your liking, any normal unity functions should work.
Some shortcomings:
You have to repeatedly press the trigger, using while() seems to break unity. This seems pretty easy to fix
The code snippet instantly translates up by 1. Not sure how to do it as a steady acceleration.
Hopefully this helps anyone who had my problem.

Make GameObject “attach” properly?

This script makes a cube "stick" to whatever it collided with. The problem is that when it's going at relatively high or medium speeds (or when the device itself is slow), the cube tends to "get a bit inside" what it collided with and then stick to it. What changes do I have to make to fix this?
In order for this script to work, one GameObject must have bool _sticksToObjects = true; and the other bool _sticksToObjects = false;
I have tried turning the Rigidbody's Collision Detection mode to either Continuous or Continuous Dynamic
I think my script depends on frame rate. That may be where the problem lies.
Normal "Attach":
Abnormal "Attach":
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's 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:
This is a well-known category of problem in game engineering and you'll be pleased to know the solution is relatively simple. You'll be pleased to hear there are similar, but much more complicated, problems that are actually solved in the same way. I'll try to explain.
Now here's the thing. It's quite often that the following question comes up...
So I'm working on GTA. I have a humanoid, H, running around. She approaches vehicle V. She opens the door and gets in and drives off. After that everything goes to hell in Mecanim and all the code stops working. What to do?
Surprisingly, the way that is done in games is:
Surprisingly: you actually swap to totally different models at that point!!!!!
You have H and V in the game. But then you have an animation (say) for H climbing in to V. But then, you literally destroy the game objects of H and V, and you Instantiate (or just awake) a new, totally different, game object, which is D ("a car being driven around by a lady").
(If you think about it, you can see that when you do this, you carefully adjust all the stuff in D, so that it matches what was "just then happening" in the frame, in relation to both H and V. So for example, literally, you copy the transform, twist etc of the car V, to the new car-inside-D, if lady H has the SmearedMakeupEffect, you put the same SmearedMakeupEffect on the lady-within-D, you position all the bones identically, and so on.)
Another simple example of this is, you often get people asking, "my character C gets killed and I want it to become a ragdoll, how to?" In fact you just swap to a totally new game object you have all set up for that passage of the game. Indeed, if you have a character A ("Arnie") in a game, it's normal that you have 4 or 5 "different As" sitting offside the stage, so, there's "ragdoll A", "A who can dance" "A with weapon". And indeed many of these are combos, you know "A on the horse" "A in the car" and so on.
So interestingly, the "real" solution here is,
once they become a new connected thing, destroy them both and swap to a new game object altogether!
if you have made games "until you are blue in the face" from making games, this is just what you would do as a matter of course. Even though its' a simple situation, it's just easier in the long run. After all, consider all the stuff you have to do when this happens:
make hitting object child of the other
turn off physics on the child
change the way your physics works for the whole thing
turn off or change the collider on the hitting object, perhaps making it part of the overall object
you'll likely have some sort of new "separation" physics where it can be knocked-off - you'd have to turn all that on
likely change minor issues like sound effects, colors etc
As you can see it's a huge chore doing all this stuff, and indeed it's one of those things it's just "easier to do properly" and change to a new model.
All that being said, I know you want a Quick Script Solution you can Paste In :) Here it is...
Step 0, You'll create "YourScript" which goes on the "main" cube. it will "catch" another cube moving around.
YourScript will look basically 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's really all you have to do.
Step 1, YOUR script must have a public bool like this
[System.NonSerialized] public bool isConnectedNow;
Step 2, Here's MyScript which goes on the hitting cube, first we'll unit-test 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 the little cube stick and unstick from the big cube .. Watch 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;
p.x = xShouldBe; // be careful it's .y, .z etc for other axes
transform.position = p;
}
for now call that in Update() in MyScript like this
void Update()
{
Debug.Log("I am " yourScript.isConnectedNow ? "free" : "stuck");
if (yourScript.isConnectedNow) DistanceCorrectionX();
}
Now actually Play and make it stick. Now, since it's running in Update simply while Play look at the Inspector for MyScript and adjust the value of correctXDistance to get the exact look you want. When yo have decided on a value, unPlay and put that in as the final value you wish.
Next, in DistanceCorrectionX simply duplicate all the code and do it again for the Y axis DistanceCorrectionX. If you also do Z, do that.
Finally. Note you will have a lot of messy code, like this...
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
}
}
and so on, there's "many little things" you'll need to do.
Don't forget also, overwhelmingly you may want to make the hitting object a child of the big object, depending on your situation. (Then of course they would move around together as a unit.)
Note that in the positioning code above I just showed it as position, not local position, for pedagogic clarity. If you want to do them flinging around, and spinning and so on, you'd make the hitting object a child of the other and you would use localPosition in the same way. Enjoy.
One possible way that comes to my mind is:
Inside of the "collision enter" check the distance between these objects and move the one that should stick to the other one a bit away.
As you see in the picture the distance between A and B should be equal to the sum of the widths divided by 2 (with a small threshold of course).
If the distance is less than the sum of the widths / 2 then you have an abnormal "attach" and you have to move one of the objects away. Its not really difficult to accomplish that.

Categories