|
18.02.2013, 22:06
|
#1
|
Бывалый
Регистрация: 21.12.2008
Адрес: UA
Сообщений: 878
Написано 105 полезных сообщений (для 357 пользователей)
|
Third Person Camera
Решил выложить некоторые свои наработки по камере от третьего лица.
Сделал два вида камер.
Первая CameraFollow как в GTA4 сама поворачивается за игроком, но что-то в ней не так и когда камера поворачивается за игроком + игрок поворачивает мышь в противоположную сторону, то начинается дрожание.
Вторая CameraOrbit как в большинстве игр от третьего лица, сама не поворачивает и движется за плечом игрока.
Так же у обеих камер есть коллизия путем пускания пяти лучей от центра и краев ближайшей плоскости отсечения камеры.
Sources http://uppit.com/0llydzih7xkh/Third_...).unitypackage
WebPlayer http://dl.dropbox.com/u/55489242/Thi...WebPlayer.html
|
(Offline)
|
|
Эти 4 пользователя(ей) сказали Спасибо WISHMASTER35 за это полезное сообщение:
|
|
18.02.2013, 22:12
|
#2
|
Бывалый
Регистрация: 21.12.2008
Адрес: UA
Сообщений: 878
Написано 105 полезных сообщений (для 357 пользователей)
|
Ответ: Third Person Camera
CameraFollow
using UnityEngine;
using System.Collections;
[ExecuteInEditMode]
public class CameraFollow : MonoBehaviour {
public Transform target;
public Vector3 targetOffset = new Vector3(0, 1.5f, 0);
private Vector3 smoothTargetPosition;
private const float minDistance = 1;
private float distance;
public float maxDistance = 7;
private float angleX = 0;
public float minAngleX = -30, maxAngleX = 50;
void OnEnable() {
if( !target ) return;
distance = maxDistance;
smoothTargetPosition = target.TransformPoint(targetOffset);
}
void FixedUpdate() {
if( !target ) return;
Vector3 targetPosition = target.TransformPoint(targetOffset);
smoothTargetPosition = Vector3.Lerp(smoothTargetPosition, targetPosition, 20*Time.deltaTime);
}
// Update is called once per frame
void LateUpdate () {
if( !target ) return;
Vector3 targetPosition = smoothTargetPosition;
Vector2 rot = GetInputRotation();
transform.RotateAround( targetPosition, Vector3.up, rot.y );
angleX = Mathf.Clamp( angleX+rot.x, minAngleX, maxAngleX );
Vector3 dir = transform.position - targetPosition;
dir.y = Mathf.Sin( angleX*Mathf.Deg2Rad ) * maxDistance;
dir = SetLength(dir, maxDistance);
float oldDistance = distance;
distance = Raycast( targetPosition, dir, dir.magnitude );
distance = Mathf.Max(distance, minDistance);
distance = Mathf.Lerp(oldDistance, distance, 10*Time.deltaTime);
transform.position = targetPosition + dir.normalized * distance;
transform.LookAt( targetPosition );
}
private static Vector3 SetLength(Vector3 v, float len) {
// задаем динну вектору, но не изменяем компоненту y
float k = (v.x*v.x + v.z*v.z) / (len*len - v.y*v.y);
k = Mathf.Sqrt(k);
if( !float.IsNaN(k) && k != 0 ) {
v.x /= k;
v.z /= k;
} else {
v.x = 0;
v.z = 0;
}
return v;
}
private static float Raycast(Vector3 start, Vector3 dir, float distance) {
RaycastHit hit = new RaycastHit();
int layerMask = 1 << LayerMask.NameToLayer("Player");
if( Physics.Raycast(start, dir, out hit, distance, ~layerMask) ) {
return hit.distance;
}
return distance;
}
private Vector2 GetInputRotation() {
#if (UNITY_ANDROID || UNITY_IOS) && !UNITY_EDITOR
return MobileInput.GetRotation();
#else
if( !Input.GetMouseButton(1) ) return Vector2.zero;
float dx = Input.GetAxis( "Mouse X" )*4;
float dy = Input.GetAxis( "Mouse Y" )*4;
return new Vector2(-dy, dx);
#endif
}
private static float ClampAngle(float angle, float min, float max) {
if (angle < -360) angle += 360;
if (angle > 360) angle -= 360;
return Mathf.Clamp(angle, min, max);
}
void OnDrawGizmosSelected() {
if(!enabled) return;
Gizmos.color = Color.red;
Gizmos.DrawSphere( target.TransformPoint( targetOffset ), 0.05f );
}
}
CameraOrbit
using UnityEngine;
using System.Collections;
public class CameraOrbit : MonoBehaviour {
public Transform target;
public Vector3 targetOffset = new Vector3(0, 1.5f, 0);
private Vector3 smoothTargetPosition;
public float minAngleX = -20, maxAngleX = 60;
private Vector3 angles;
private const float minDistance = 1.0f;
private float distance;
public float maxDistance = 7.0f;
public Vector3 cameraOffset = new Vector3(1, 0, 0);
void OnEnable() {
if( !target ) return;
angles = transform.eulerAngles;
distance = maxDistance;
smoothTargetPosition = target.TransformPoint(targetOffset);
}
void FixedUpdate() {
if( !target ) return;
Vector3 targetPosition = target.TransformPoint(targetOffset);
smoothTargetPosition = Vector3.Lerp(smoothTargetPosition, targetPosition, 20*Time.deltaTime);
}
void LateUpdate () {
if( !target ) return;
angles += GetInputRotation();
angles.x = ClampAngle(angles.x, minAngleX, maxAngleX);
Quaternion rotation = Quaternion.Euler(angles);
Quaternion smoothRotation = Quaternion.Slerp(transform.rotation, rotation, 20*Time.deltaTime);
ComputeTransform(smoothTargetPosition, smoothRotation, maxDistance, cameraOffset);
CollisionTest(smoothTargetPosition);
}
private void ComputeTransform(Vector3 targetPosition, Quaternion rotation, float distance, Vector3 cameraOffset) {
transform.rotation = rotation;
transform.position = targetPosition;
transform.Translate(0, 0, -distance);
transform.Translate(cameraOffset * distance);
}
private void CollisionTest(Vector3 targetPosition) {
float newDistance = CameraCollider.CollisionTest(camera, targetPosition, maxDistance);
newDistance = Mathf.Max(newDistance, 0.5f);
newDistance = Mathf.Lerp(distance, newDistance, 10*Time.deltaTime);
Vector3 dir = transform.position - targetPosition;
transform.position = targetPosition + dir.normalized * newDistance;
distance = newDistance;
}
private static float ClampAngle(float angle, float min, float max) {
if (angle < -360) angle += 360;
if (angle > 360) angle -= 360;
return Mathf.Clamp (angle, min, max);
}
private Vector3 GetInputRotation() {
#if (UNITY_ANDROID || UNITY_IOS) && !UNITY_EDITOR
return MobileInput.GetRotation();
#else
if( !Input.GetMouseButton(1) ) return Vector2.zero;
float dx = Input.GetAxis( "Mouse X" )*4;
float dy = Input.GetAxis( "Mouse Y" )*4;
return new Vector2(-dy, dx);
#endif
}
void OnDrawGizmosSelected() {
if(!enabled) return;
CameraCollider.DrawFrustum(camera, smoothTargetPosition);
Gizmos.color = Color.red;
Gizmos.DrawSphere( smoothTargetPosition, 0.05f );
}
}
CameraCollider
using UnityEngine;
using System.Collections;
public class CameraCollider {
public static float CollisionTest(Camera camera, Vector3 targetPosition, float dis) {
NearClipPlane plane = new NearClipPlane(camera);
dis = Mathf.Min( dis, Raycast(targetPosition, plane.center) );
dis = Mathf.Min( dis, Raycast(targetPosition, plane.lowerLeft) );
dis = Mathf.Min( dis, Raycast(targetPosition, plane.lowerRight) );
dis = Mathf.Min( dis, Raycast(targetPosition, plane.upperLeft) );
dis = Mathf.Min( dis, Raycast(targetPosition, plane.upperRight) );
return dis;
}
private static float Raycast(Vector3 start, Vector3 end) {
Vector3 dir = end - start;
float distance = dir.magnitude;
RaycastHit hit = new RaycastHit();
int layerMask = 1 << LayerMask.NameToLayer("Player");
if( Physics.Raycast(start, dir, out hit, distance, ~layerMask) ) {
return hit.distance;
}
return distance;
}
public static void DrawFrustum(Camera camera, Vector3 target) {
NearClipPlane plane = new NearClipPlane(camera);
Gizmos.DrawLine(target, plane.center);
Gizmos.DrawLine(target, plane.upperRight);
Gizmos.DrawLine(target, plane.upperLeft);
Gizmos.DrawLine(target, plane.lowerRight);
Gizmos.DrawLine(target, plane.lowerLeft);
Gizmos.DrawLine(plane.upperRight, plane.upperLeft);
Gizmos.DrawLine(plane.upperRight, plane.lowerRight);
Gizmos.DrawLine(plane.lowerLeft, plane.lowerRight);
Gizmos.DrawLine(plane.lowerLeft, plane.upperLeft);
}
}
struct NearClipPlane {
private const float scale = 2f;
//Точки, определяющие положение ближней плоскостиотсечения камеры
public Vector3 center;
public Vector3 upperLeft;
public Vector3 upperRight;
public Vector3 lowerLeft;
public Vector3 lowerRight;
public NearClipPlane(Camera camera) {
Transform trans = camera.transform;
Vector3 pos = trans.position;
float height = camera.nearClipPlane * Mathf.Tan((camera.fieldOfView / 2f) * Mathf.Deg2Rad);
float width = height * camera.aspect;
//рассчитываем положение точек
Vector3 right = trans.right * width * scale;
Vector3 up = trans.up * height * scale;
center = pos + trans.forward * camera.nearClipPlane;
lowerRight = center + right - up;
lowerLeft = center - right - up;
upperRight = center + right + up;
upperLeft = center - right + up;
}
}
|
(Offline)
|
|
Ваши права в разделе
|
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 17:05.
|