Извините, ничего не найдено.

Не расстраивайся! Лучше выпей чайку!
Регистрация
Справка
Календарь

Вернуться   forum.boolean.name > Программирование игр для компьютеров > Unity > Уроки

Ответ
 
Опции темы
Старый 18.02.2013, 22:06   #1
WISHMASTER35
Бывалый
 
Аватар для WISHMASTER35
 
Регистрация: 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 за это полезное сообщение:
Andvrok (19.02.2013), Arles (22.04.2013), pax (19.02.2013), Radnk (08.04.2013)
Старый 18.02.2013, 22:12   #2
WISHMASTER35
Бывалый
 
Аватар для WISHMASTER35
 
Регистрация: 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)
 
Ответить с цитированием
Ответ


Опции темы

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.


Часовой пояс GMT +4, время: 15:51.


vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot
Style crйe par Allan - vBulletin-Ressources.com