带碰撞检测的摄像机

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




// 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;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值