I've been working with Unity for some while to try to create basic games. Lately, I've been running into a problem. I'm using the script in the 3D Platform Game for my camera and character. I like how it works, but lately, I've been running into a problem with the camera. It's great, but when I run into a hill in the terrain, you can see through it which kinda ruins the effect. I've seen ray casting done on this stuff, but I"m a n00b at this, and the scripts other's supply don't really get that effect I want. Thanks in advance if you can help :D
Here's a slightly tidied-up/tested version of Tetrad's C# script - it zooms smoothly back out after you get too close to a wall (the other one stays close to your character after going towards a wall and back). Just need to attach it to a camera (that's parented to the object being moved).
using UnityEngine;
using System.Collections;
public class CameraCollision : MonoBehaviour {
public float minDistance = 1.0f;
public float maxDistance = 4.0f;
public float smooth = 10.0f;
Vector3 dollyDir;
float distance;
void Awake()
{
dollyDir = transform.localPosition.normalized;
distance = transform.localPosition.magnitude;
}
void Update()
{
Vector3 desiredCameraPos = transform.parent.TransformPoint( dollyDir * maxDistance );
RaycastHit hit;
if( Physics.Linecast( transform.parent.position, desiredCameraPos, out hit ) )
{
distance = Mathf.Clamp( hit.distance, minDistance, maxDistance );
}
else
{
distance=maxDistance;
}
transform.localPosition=Vector3.Lerp(transform.localPosition, dollyDir * distance, Time.deltaTime * smooth);
}
}
or…
private void compensateForWalls(Vector3 fromObject, ref Vector3 toTarget)
{
Debug.DrawLine (fromObject, toTarget, Color.cyan);
RaycastHit wallHit = new RaycastHit ();
if(Physics.Linecast(fromObject, toTarget, out wallHit))
{
Debug.DrawRay(wallHit.point, wallHit.normal, Color.red);
Vector3 wallHitVector3 = new Vector3 (wallHit.point.x, wallHit.point.y, wallHit.point.z);
toTarget = new Vector3 (wallHitVector3.x, toTarget.y, wallHitVector3.z);
}
}
This is untested, but should get the point across. I've ripped apart a script that we're using in the game here but with the mouse wheel (or -/= keys) move in/out stuff taken out.
Just make a new class (C#) and drop this in there and attach it to your camera object.
For this script I assume that the hierarchy is something like player base (ground) -> player shoulder-ish -> camera (placed away from the shoulders kind of like a dolly).
public float minDistance = 1.0f;
public float maxDistance = 10.0f;
Vector3 dollyDir;
float distance;
void Awake()
{
dollyDir = transform.localPosition.normalized;
distance = transform.localPosition.magnitude;
}
void Update()
{
Vector3 desiredCameraPos = transform.parent.TransformPoint( dollyDir * distance );
// (optional) put layers you don't want to collide with here (probably things like enemies)
const int ignoreLayer1 = 1 << 18;
const int ignoreLayer2 = 1 << 19;
int layerMask = ignoreLayer1 | ignorelayer2;
layerMask = ~layerMask;
RaycastHit hit;
if( Physics.Linecast( transform.parent.position, desiredCameraPos, out hit, layerMask ) )
{
distance = Mathf.Clamp( hit.distance, minDistance, maxDistance );
}
transform.localPosition = dollyDir * distance;
}