How can I make an object stick to a surface, but still let me add forces to the object.
I am trying to make a game with a pipe and ball , however whenever you go on one of the sides of tube and try to move the opposite direction the balls just flys through the air. I want to make it so the ball is stuck to the tube.
Hi @george_wilkes - is this game 2D or 3D? What kind of pipe are we talking about - one with 90 degree corners, or some spline like tube? Are we traveling on inner surface of the pipe or on the outer surface? It is quite hard to give specific answer to such a vague question, but in general, you could try manipulating physics system gravity direction to match pipe's surface normal at current frame. See other threads on topic: https://answers.unity.com/questions/36815/gravity-direction-change.html
Answer by UnityCoach · Aug 11, 2018 at 09:36 PM
Hey, try this.
#define AUTO_DISABLE
#define DEBUG_DISPLAY
using UnityEngine;
[RequireComponent (typeof (Rigidbody))]
[RequireComponent (typeof (Collider))]
public class Sticky : MonoBehaviour
{
[Tooltip ("Surface Rigidbody to Stick To.")]
[SerializeField] Rigidbody _surfaceBody;
[Tooltip ("Use Force to attract object to surface.\n" +
"Moves position when off.")]
[SerializeField] bool _useForce;
[SerializeField] float _forceMultiplier = 1f;
[SerializeField] ForceMode _forceMode = ForceMode.VelocityChange;
Collider _surfaceCollider;
Rigidbody _rigidbody;
Collider _collider;
Vector3 _origin, _destination, _offset, _delta, _target;
void Awake ()
{
_rigidbody = GetComponent<Rigidbody>();
_collider = GetComponent<Collider>();
_surfaceCollider = _surfaceBody.GetComponent<Collider>();
}
void FixedUpdate ()
{
_destination = _surfaceCollider.ClosestPoint(_rigidbody.position);
_origin = _collider.ClosestPoint(_destination);
_delta = _destination - _origin;
_offset = _origin - _rigidbody.position;
_target = _destination - _offset;
if (_useForce)
_rigidbody.AddForce(_delta * _forceMultiplier, _forceMode);
else
_rigidbody.MovePosition(_target);
}
#if AUTO_DISABLE
void OnCollisionEnter (Collision col)
{
if (col.rigidbody == _surfaceBody)
enabled = false;
}
void OnCollisionExit (Collision col)
{
if (col.rigidbody == _surfaceBody)
enabled = true;
}
#endif
#if DEBUG_DISPLAY
void OnDrawGizmos ()
{
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(_origin, 0.1f);
Gizmos.color = Color.cyan;
Gizmos.DrawWireSphere(_destination, 0.1f);
Gizmos.color = Color.green;
Gizmos.DrawRay(_origin, _delta);
Gizmos.color = Color.red;
Gizmos.DrawWireSphere(_target, 0.1f);
}
#endif
}
Your answer
Follow this Question
Related Questions
How Do I Create a List of Two Strings? C# 1 Answer
How to remove flashing screen when changing Canvas Render Modes 0 Answers
Can’t keep the position 0 Answers
[C#] Enum not working properly 2 Answers