[unity3d]第三人称视角相关脚本

简介: //第三人称摄像机更随var cameraTransform : Transform; //跟随相机private var _target : Transform; //跟随物体// The distance in the x-z plane to the targetvar distance = 7.


//第三人称摄像机更随


var cameraTransform : Transform;    //跟随相机
private var _target : Transform;    //跟随物体

// The distance in the x-z plane to the target

var distance = 7.0;   //相机距离物理的距离

// the height we want the camera to be above the target
var height = 3.0;  //相机距离物体的高度

var angularSmoothLag = 0.3;  
var angularMaxSpeed = 15.0;

var heightSmoothLag = 0.3;

var snapSmoothLag = 0.2;
var snapMaxSpeed = 720.0;

var clampHeadPositionScreenSpace = 0.75;

var lockCameraTimeout = 0.2;

private var headOffset = Vector3.zero;
private var centerOffset = Vector3.zero;

private var heightVelocity = 0.0;
private var angleVelocity = 0.0;
private var snap = false;
private var controller : ThirdPersonController;
private var targetHeight = 100000.0;    

function Awake ()
{
	if(!cameraTransform && Camera.main)
		cameraTransform = Camera.main.transform;  //获取主相机
	if(!cameraTransform) {
		Debug.Log("Please assign a camera to the ThirdPersonCamera script.");
		enabled = false;	
	}
			
		
	_target = transform;
	if (_target)
	{
		controller = _target.GetComponent(ThirdPersonController);  
	}
	
	if (controller)
	{
		var characterController : CharacterController = _target.collider;
		centerOffset = characterController.bounds.center - _target.position;
		headOffset = centerOffset;
		headOffset.y = characterController.bounds.max.y - _target.position.y;
	}
	else
		Debug.Log("Please assign a target to the camera that has a ThirdPersonController script attached.");

	
	Cut(_target, centerOffset);
}

function DebugDrawStuff ()
{
	Debug.DrawLine(_target.position, _target.position + headOffset);

}

function AngleDistance (a : float, b : float)
{
	a = Mathf.Repeat(a, 360);
	b = Mathf.Repeat(b, 360);
	
	return Mathf.Abs(b - a);
}

function Apply (dummyTarget : Transform, dummyCenter : Vector3)
{
	// Early out if we don't have a target
	if (!controller)
		return;
	
	var targetCenter = _target.position + centerOffset;
	var targetHead = _target.position + headOffset;

//	DebugDrawStuff();

	// Calculate the current & target rotation angles
	var originalTargetAngle = _target.eulerAngles.y;
	var currentAngle = cameraTransform.eulerAngles.y;

	// Adjust real target angle when camera is locked
	var targetAngle = originalTargetAngle; 
	
	// When pressing Fire2 (alt) the camera will snap to the target direction real quick.
	// It will stop snapping when it reaches the target
	if (Input.GetButton("Fire2"))
		snap = true;
	
	if (snap)
	{
		// We are close to the target, so we can stop snapping now!
		if (AngleDistance (currentAngle, originalTargetAngle) < 3.0)
			snap = false;
		
		currentAngle = Mathf.SmoothDampAngle(currentAngle, targetAngle, angleVelocity, snapSmoothLag, snapMaxSpeed);
	}
	// Normal camera motion
	else
	{
		if (controller.GetLockCameraTimer () < lockCameraTimeout)
		{
			targetAngle = currentAngle;
		}

		// Lock the camera when moving backwards!
		// * It is really confusing to do 180 degree spins when turning around.
		if (AngleDistance (currentAngle, targetAngle) > 160 && controller.IsMovingBackwards ())
			targetAngle += 180;

		currentAngle = Mathf.SmoothDampAngle(currentAngle, targetAngle, angleVelocity, angularSmoothLag, angularMaxSpeed);
	}


	// When jumping don't move camera upwards but only down!
	if (controller.IsJumping ())
	{
		// We'd be moving the camera upwards, do that only if it's really high
		var newTargetHeight = targetCenter.y + height;
		if (newTargetHeight < targetHeight || newTargetHeight - targetHeight > 5)
			targetHeight = targetCenter.y + height;
	}
	// When walking always update the target height
	else
	{
		targetHeight = targetCenter.y + height;
	}

	// Damp the height
	var currentHeight = cameraTransform.position.y;
	currentHeight = Mathf.SmoothDamp (currentHeight, targetHeight, heightVelocity, heightSmoothLag);

	// Convert the angle into a rotation, by which we then reposition the camera
	var currentRotation = Quaternion.Euler (0, currentAngle, 0);
	
	// Set the position of the camera on the x-z plane to:
	// distance meters behind the target
	cameraTransform.position = targetCenter;
	cameraTransform.position += currentRotation * Vector3.back * distance;

	// Set the height of the camera
	cameraTransform.position.y = currentHeight;
	
	// Always look at the target	
	SetUpRotation(targetCenter, targetHead);
}

function LateUpdate () {
	Apply (transform, Vector3.zero);
}



function Cut (dummyTarget : Transform, dummyCenter : Vector3)
{
	var oldHeightSmooth = heightSmoothLag;
	var oldSnapMaxSpeed = snapMaxSpeed;
	var oldSnapSmooth = snapSmoothLag;
	
	snapMaxSpeed = 10000;
	snapSmoothLag = 0.001;
	heightSmoothLag = 0.001;
	
	snap = true;
	Apply (transform, Vector3.zero);
	
	heightSmoothLag = oldHeightSmooth;
	snapMaxSpeed = oldSnapMaxSpeed;
	snapSmoothLag = oldSnapSmooth;
}

function SetUpRotation (centerPos : Vector3, headPos : Vector3)
{
	// Now it's getting hairy. The devil is in the details here, the big issue is jumping of course.
	// * When jumping up and down we don't want to center the guy in screen space.
	//  This is important to give a feel for how high you jump and avoiding large camera movements.
	//   
	// * At the same time we dont want him to ever go out of screen and we want all rotations to be totally smooth.
	//
	// So here is what we will do:
	//
	// 1. We first find the rotation around the y axis. Thus he is always centered on the y-axis
	// 2. When grounded we make him be centered
	// 3. When jumping we keep the camera rotation but rotate the camera to get him back into view if his head is above some threshold
	// 4. When landing we smoothly interpolate towards centering him on screen
	var cameraPos = cameraTransform.position;
	var offsetToCenter = centerPos - cameraPos;
	
	// Generate base rotation only around y-axis
	var yRotation = Quaternion.LookRotation(Vector3(offsetToCenter.x, 0, offsetToCenter.z));

	var relativeOffset = Vector3.forward * distance + Vector3.down * height;
	cameraTransform.rotation = yRotation * Quaternion.LookRotation(relativeOffset);

	// Calculate the projected center position and top position in world space
	var centerRay = cameraTransform.camera.ViewportPointToRay(Vector3(.5, 0.5, 1));
	var topRay = cameraTransform.camera.ViewportPointToRay(Vector3(.5, clampHeadPositionScreenSpace, 1));

	var centerRayPos = centerRay.GetPoint(distance);
	var topRayPos = topRay.GetPoint(distance);
	
	var centerToTopAngle = Vector3.Angle(centerRay.direction, topRay.direction);
	
	var heightToAngle = centerToTopAngle / (centerRayPos.y - topRayPos.y);

	var extraLookAngle = heightToAngle * (centerRayPos.y - centerPos.y);
	if (extraLookAngle < centerToTopAngle)
	{
		extraLookAngle = 0;
	}
	else
	{
		extraLookAngle = extraLookAngle - centerToTopAngle;
		cameraTransform.rotation *= Quaternion.Euler(-extraLookAngle, 0, 0);
	}
}

function GetCenterOffset ()
{
	return centerOffset;
}


相关文章
|
存储 缓存 JSON
Unity资源热更新知识梳理及工作流介绍
研究了大半年的热更,才做出了一套相对完善的热更架构。不得不说,这块的知识点还是多而杂的,值得专门开篇博文来记录梳理。
2259 0
|
4月前
|
人工智能 算法 BI
Unity——脚本与导航系统
Unity——脚本与导航系统
|
5月前
|
前端开发 C# 开发工具
Unity快手上手【熟悉unity编辑器,C#脚本控制组件一些属性之类的】
Unity快手上手【熟悉unity编辑器,C#脚本控制组件一些属性之类的】
105 0
|
10月前
|
人工智能 API 图形学
unity基础脚本代码总结
unity基础脚本代码总结
141 0
|
存储 JavaScript C#
从零开始做一款Unity3D游戏<三>——编写游戏机制(一)
从零开始做一款Unity3D游戏<三>——编写游戏机制
从零开始做一款Unity3D游戏<三>——编写游戏机制(一)
|
存储 设计模式 JavaScript
从零开始做一款Unity3D游戏<三>——编写游戏机制(二)
从零开始做一款Unity3D游戏<三>——编写游戏机制
从零开始做一款Unity3D游戏<三>——编写游戏机制(二)
|
图形学
修改预制体效果无变化(unity&&CocosCreator)
修改预制体效果无变化(unity&&CocosCreator)
|
安全 图形学 Windows
unity程序使用云渲染技术是否要修改?
unity引擎开发的程序使用了点量云渲染系统后,为啥不用对程序修改就可以实现手机和平板中直接使用呢?这是因为云渲染系统,对于操控方式是键盘或者鼠标的Unity或者UE4程序,会在手机中模拟出鼠摇杆和软键盘,这样就可以像在电脑上一样完成交互了。当然如果手机或者平板能连蓝牙,也可以外接鼠标完成交互。**所以使用实时云渲染技术是无需对现有程序做修改的,程序在Windows使用是如何建模的,还是按照原来的方式建模即可
254 0
unity程序使用云渲染技术是否要修改?
|
vr&ar 图形学
【Unity3D 灵巧小知识点】☀️ | Unity脚本生命周期
Unity小科普 老规矩,先介绍一下 Unity 的科普小知识: Unity是 实时3D互动内容创作和运营平台 。 包括游戏开发、美术、建筑、汽车设计、影视在内的所有创作者,借助 Unity 将创意变成现实。 Unity 平台提供一整套完善的软件解决方案,可用于创作、运营和变现任何实时互动的2D和3D内容,支持平台包括手机、平板电脑、PC、游戏主机、增强现实和虚拟现实设备。 也可以简单把 Unity 理解为一个游戏引擎,可以用来专业制作游戏!
【Unity3D 灵巧小知识点】☀️ | Unity脚本生命周期
|
开发框架 Java .NET
优化Unity游戏项目的脚本(上)
本文将由捷克独立游戏工作室Lonely Vertex的开发工程师Ondřej Kofroň,分享C#脚本的一系列优化方法,并提供改进Unity游戏性能的最佳实践。 在开发游戏时,我们遇到了游戏过程中偶尔出现延迟的问题。