带碰撞检测的摄像机

原文地址:http://blog.sina.com.cn/s/blog_4a2183a601018fmd.html


类似网游那样如果摄像机和目标之间有其他物体存在,就移动摄像机到障碍物前面





// CamController
// 带碰撞第三人称摄像机
//Edit by Shadou
//编写 傻逗
//
//create at 2011-8-4
//last change 2011-10-9
//
//Any bugs and suggestions please e-mail to 51149526@qq.com or visit my blog
//
//
 
@script AddComponentMenu ("SDTK/Camera/Thrid person Cam")
var target : Transform; //目标物体
var mask: LayerMask;//layer层           //只检测在mask 包含的层里的碰撞体是否会遮挡视线
 
var targetHeight = 2.0; //实际聚焦点位置处于目标坐标上方的高度值          //不宜过高,否则会影响视线检测的位置
var distance = 5.0;// 摄像机距离实际聚焦点的距离
 
var maxDistance = 20; //摄像机距离实际聚焦点的最大距离
var minDistance = 2.5; //摄像机距离实际聚焦点的最小距离
 
var xSpeed = 250.0; //横向移动速度(eulerAngles.y)
var ySpeed = 120.0; //纵向移动速度(eulerAngles.x)
 
var yMinLimit = -20; //摄像机仰角(eulerAngles.x)最小值
var yMaxLimit = 80; //摄像机仰角(eulerAngles.x)最大值
 
var zoomRate = 20; //推拉摄像机的速度
 
var rotationDampening = 2.0; //摄像机移动阻尼              //数值越小摄像机停止的速度越慢, 数值越高停止的速度越快
 
private var x = 0.0; //水平旋转角度
private var y = 0.0; //仰角旋转角度
 
private var xDampMove: float=0;//水平旋转阻尼速度
private var yDampMove: float=0;//仰角旋转阻尼速度
 
private var targetDistance: float=0;
 
 
function Awake () {
    var angles = transform.eulerAngles;
    x = angles.y;
    y = angles.x;
 
       // Make the rigid body not change rotation
       //防止刚体影响物体旋转
       if (rigidbody)
              rigidbody.freezeRotation = true;
             
       targetDistance=distance;
}
 
//摄像机位移应该在所有其他物体计算之后处理            //LateUpdate 晚于 Update
//防止摄像机移动后有其他物体移动道遮挡的位置, 或者与目标物体位移不同步
function LateUpdate () {
   if(!target)
      return;
      
       // If either mouse buttons are down, let them govern camera position
       //鼠标点击移动摄像机
       if(Input.GetMouseButton(2) || Input.GetMouseButton(1)){
              xDampMove=Input.GetAxis("Mouse X") * xSpeed;
              yDampMove=Input.GetAxis("Mouse Y") * ySpeed;
       }
      
       // move cam using arrow keys
       //使用键盘移动摄像机
       //~xDampMove-=(xDampMove<xSpeed/2f)?(Input.GetAxis("Horizontal")*xSpeed*0.25f):0;
       //~ yDampMove-=(xDampMove<xSpeed/2f)?(Input.GetAxis("Vertical")*ySpeed*0.25f):0;
      
       //clamp speed
       //限制移动速度最大值
       xDampMove=Mathf.Clamp(xDampMove,-xSpeed,xSpeed);
       yDampMove=Mathf.Clamp(yDampMove,-ySpeed,ySpeed);
      
       //apply
       //施加摄像机移动
       x+=xDampMove*Time.deltaTime;
       y-=yDampMove*Time.deltaTime;
      
       //distance change
       //更改摄像机与目标之间的距离
       if(Input.GetKey("q"))
              distance-=zoomRate*0.25f*Time.deltaTime;
      
       if(Input.GetKey("e"))
              distance+=zoomRate*0.25f*Time.deltaTime;
      
       distance -= (Input.GetAxis("Mouse ScrollWheel") * Time.deltaTime) * zoomRate * Mathf.Abs(distance);
       distance = Mathf.Clamp(distance, minDistance, maxDistance);
   
       //缩放施加阻尼
       targetDistance=Mathf.Lerp(targetDistance,distance,2*Time.deltaTime);
      
       //限制仰角
       y = ClampAngle(y, yMinLimit, yMaxLimit);
   
       //calcu
       //计算摄像机的角度和方向
       var rotation : Quaternion = Quaternion.Euler(y, x, 0);
       var position : Vector3= rotation * Vector3.forward * -targetDistance + target.position+Vector3(0,targetHeight,0);
   
       //slowDown
       //对摄像机的移动施加阻尼
       xDampMove=Mathf.Lerp(xDampMove,0,rotationDampening*Time.deltaTime);
       yDampMove=Mathf.Lerp(yDampMove,0,rotationDampening*Time.deltaTime);
 
      
       //checkLineOfSign and Collision
       //检测是否有碰撞体遮挡视线
       //如果有则移动摄像机的位置到障碍物前面
       position=SignUpdate(target.position+Vector3.up*targetHeight,position,0.3f, distance,0.6f,mask);
      
       //change distance if want
       //更改摄像机位置的同时更改距离    如果需要
       //开启时摄像机离开障碍物遮挡后不会突然跳跃
       //
       targetDistance=Vector3.Distance(position,target.position+Vector3.up*targetHeight);
       //
      
      
       //Apply
       //施加摄像机位移和旋转
       transform.rotation=rotation;
       transform.position=position;
      
}
 
//限制角度
static function ClampAngle (angle : float, min : float, max : float) {
   if (angle < -360)
      angle += 360;
   if (angle > 360)
      angle -= 360;
   return Mathf.Clamp (angle, min, max);
}
 
//检测是否有碰撞体遮挡在 targetPoint 和 selfPosition 之间
//targetPoint                         目标位置
//selfPosition                 自身位置
//checkRadios                      球星检测区域半径
//maxDis                             最大检测距离
//stepDis                              检测倒碰撞后向前偏移的位置,  建议大于检测半径*2
//s_mask                             碰撞检测遮罩
function SignUpdate(targetPoint: Vector3, selfPosition: Vector3, checkRadios: float, maxDis: float, stepDis: float, s_mask: LayerMask): Vector3{
       var ray: Ray=new Ray(targetPoint,selfPosition-targetPoint);
       var hit: RaycastHit;
      
       if(Physics.SphereCast(ray,checkRadios,hit,maxDis,s_mask)){
             
              return ray.GetPoint(hit.distance-stepDis);
       }
      
       //无碰撞返回原始位置
       return selfPosition;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值