From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
(Removing all content from page)
Line 1: Line 1:
[[Category: Physics]]
[[Category: MonoBehaviour]]
[[Category: JavaScript]]
Author: Daniel Brauer, [[User:Adrian|Adrian]]
This script uses raycasting to avoid the physics engine letting fast-moving objects go through other objects (particularly meshes).
v1.1 (Boo):
* Added "Switch To Layer" convenience option to move the game object to a given layer and remove that layer from the layer mask (the original layer is restored if used together with "Time to Live").
* Added "Time to Live" option to automatically destroy the script after a given time to reduce raycasts and instances.
* Moved initialization to an Init method to make the script more usable if added through script.
Attach the script to any object that might move fast enough to go through other colliders. Make sure that the LayerMask does not include the layer of the object the script is attached to, otherwise the object will collide with itself. Leave Skin Width at 0.1 unless the object still passes through other colliders. If this happens, increase the skin width until the issue stops or you reach a value of 1.0.
==JavaScript - DontGoThroughThings.js==
#pragma strict
var layerMask : LayerMask; //make sure we aren't in this layer
var skinWidth : float = 0.1; //probably doesn't need to be changed
private var minimumExtent : float;
private var partialExtent : float;
private var sqrMinimumExtent : float;
private var previousPosition : Vector3;
private var myRigidbody : Rigidbody;
//initialize values
function Awake() {
  myRigidbody = rigidbody;
  previousPosition = myRigidbody.position;
  minimumExtent = Mathf.Min(Mathf.Min(collider.bounds.extents.x, collider.bounds.extents.y), collider.bounds.extents.z);
  partialExtent = minimumExtent*(1.0 - skinWidth);
  sqrMinimumExtent = minimumExtent*minimumExtent;
function FixedUpdate() {
  //have we moved more than our minimum extent?
  if ((previousPosition - myRigidbody.position).sqrMagnitude > sqrMinimumExtent) {
      var movementThisStep : Vector3 = myRigidbody.position - previousPosition;
      var movementMagnitude : float = movementThisStep.magnitude;
      var hitInfo : RaycastHit;
      //check for obstructions we might have missed
      if (Physics.Raycast(previousPosition, movementThisStep, hitInfo, movementMagnitude, layerMask.value))
        myRigidbody.position = hitInfo.point - (movementThisStep/movementMagnitude)*partialExtent;
  previousPosition = myRigidbody.position;
==Boo -
(See [ Script Compilation] as for how Boo scripts can be used from JavaScript and C#).
<boo>import UnityEngine
# DontGoThroughThings v1.1
# Created by Adrian on 2008-10-29.
# Original Script by Daniel Brauer
class DontGoThroughThings (MonoBehaviour):
# ---------------------------------------- #
# Layers the Raycast checks against
# The game object of this script should not be on
# a layer set in this mask or it will collide with itself.
public layerMask as LayerMask = System.Int32.MaxValue
# How far the object is set into the object it
# shoud have collided with to force a physics collision
# (Should probably be fine at 0.1 and must be between 0 and 1)
public skinWidth as single = 0.1
# Move the game object to this layer and remove
# the layer from the layer mask. This is a convenience
# feature to make sure the game object doesn't collide
# with itself. (set to -1 to disable)
public switchToLayer as int = -1
# Time in seconds before the script destroys itself
# after it has been created or initialized.
# Convenient to protected the game object only for
# a critical time to avoid useless raycasts.
# (set to -1 to disable)
public timeToLive as single = -1
# ---------------------------------------- #
private startTime as single
private originalLayer as int = -1
private minimumExtent as single
private partialExtent as single
private sqrMinimumExtent as single
private previousPosition as Vector3
private myRigidbody as Rigidbody
# ---------------------------------------- #
# Initialize the script on awake.
def Awake():
Init(timeToLive, switchToLayer)
# Initialize method to be used when adding
# this component from a script.
def Init(ttl as single, layer as int):
# Switch layer of game object
if (layer >= 0):
originalLayer = gameObject.layer
gameObject.layer = layer
switchToLayer = layer
# Clear the layer in the layer mask
layerMask = layerMask.value & ~(1 << gameObject.layer)
# Time to live
if (ttl >= 0):
startTime = Time.time
timeToLive = ttl
# Initialize variables
myRigidbody = rigidbody
previousPosition = myRigidbody.position
minimumExtent = Mathf.Min(Mathf.Min(
sqrMinimumExtent = minimumExtent ** 2
partialExtent = minimumExtent*(1.0 - skinWidth)
# Collision checking
def FixedUpdate():
# Check time to live
if (timeToLive > 0 and Time.time > startTime + timeToLive):
# Restore original layer
if (originalLayer >= 0):
gameObject.layer = originalLayer
# Only check for missed collisions if the game object moved more than its minimum extent
if (myRigidbody and (previousPosition - myRigidbody.position).sqrMagnitude > sqrMinimumExtent):
movementThisStep = myRigidbody.position - previousPosition
movementMagnitude = movementThisStep.magnitude
hitInfo as RaycastHit
if (Physics.Raycast(previousPosition, movementThisStep, hitInfo,
movementMagnitude, layerMask.value)):
# Move rigidbody back to right before the collision was missed
hitInfo.point - (movementThisStep / movementMagnitude) * partialExtent)
previousPosition = myRigidbody.position</boo>

Revision as of 18:26, 19 October 2009

Personal tools