DontGoThroughThings

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]]
 
==Description==
 
This script uses raycasting to avoid the physics engine letting fast-moving objects go through other objects (particularly meshes).
 
  
==Changes==
 
 
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.
 
 
==Usage==
 
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==
 
<javascript>
 
#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;
 
}</javascript>
 
 
==Boo - DontGoThroughThings.boo==
 
(See [http://unity3d.com/support/documentation/ScriptReference/index.Script_compilation_28Advanced29.html 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):
 
 
# ---------------------------------------- #
 
# PUBLIC FIELDS
 
 
# 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 FIELDS
 
 
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
 
 
# ---------------------------------------- #
 
# METHODS
 
 
# 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(
 
cast(single,collider.bounds.extents.x),
 
cast(single,collider.bounds.extents.y)),
 
cast(single,collider.bounds.extents.z))
 
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
 
Destroy(self)
 
return
 
 
# 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
 
myRigidbody.MovePosition(
 
hitInfo.point - (movementThisStep / movementMagnitude) * partialExtent)
 
 
previousPosition = myRigidbody.position</boo>
 

Revision as of 18:26, 19 October 2009

Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox