//int ViewIndex = 0; protected void CameraSmoothFollow(bool smooth = true) { float CameraRadis = 0.0f; float angleY = 0;//此角度由目标与玩家间的距离的来计算,距离越近越大 Vector3 newPos = Vector3.zero; Vector3 vecTarget = Vector3.zero; Vector3 wallHitPos = Vector3.zero;//撞到墙壁的位置 if (UnitTarget.LockTarget != null) { //观察格斗的双方 LockTarget = UnitTarget.LockTarget.transform; //有锁定目标 //开启摄像机锁定系统 CameraLookAt.position = ((Target.position + LockTarget.position) / 2 + new Vector3(0, 25, 0)); CameraRadis = Vector3.Distance(Target.position, LockTarget.position) / 2 + 60; float dis = Vector3.Distance(new Vector3(Target.position.x, 0, Target.position.z), new Vector3(LockTarget.position.x, 0, LockTarget.position.z)); Vector3 vecDiff = Target.position - LockTarget.position; Vector3 vecForward = Vector3.Normalize(new Vector3(vecDiff.x, 0, vecDiff.z)); //最远时,15度,最近时95度,其他值。10码 = 80度 140码 15度 约为 y = -0.5x + 85 //半径最低65,最高 angleY = -0.5f * dis + 95; float yHeight = Mathf.Tan(LookAtAngle * Mathf.Deg2Rad) * CameraRadis; newViewIndex[0] = CameraLookAt.position + Quaternion.AngleAxis(-angleY, Vector3.up) * vecForward * CameraRadis; newViewIndex[0].y += yHeight; newViewIndex[1] = CameraLookAt.position + Quaternion.AngleAxis(angleY, Vector3.up) * vecForward * CameraRadis; newViewIndex[1].y += yHeight; newViewIndex[2] = CameraLookAt.position + Quaternion.AngleAxis(-angleY, Target.right) * vecForward * CameraRadis;//顶部最后考虑 //vecTarget[0] = newViewIndex[ViewIndex]; //vecTarget[1] = newViewIndex[(ViewIndex + 1) % 3]; //vecTarget[2] = newViewIndex[(ViewIndex + 2) % 3]; //重新排。当前排第一,顶部排最后,剩下的排第二。这样切换就不会那么频繁. //for (int i = 0; i < 3; i++) // m_Targets[i].position = newViewIndex[i]; dis = 1000.0f; for (int i = 0; i < 2; i++) { if (Utility.CameraCanLookTarget(UnitTarget, newViewIndex[i], out wallHitPos)) { float fdis = Vector3.Distance(newViewIndex[i], transform.position); if (fdis < dis) { dis = fdis; vecTarget = newViewIndex[i]; } } else { float fdis = Vector3.Distance(wallHitPos, transform.position); float disWall = Vector3.Distance(wallHitPos, CameraLookAt.position);//墙壁与看向目标的距离一定要足够,否则视角堵着很难受. if (fdis < dis && disWall > 40.0f) { dis = fdis; vecTarget = wallHitPos; } } } //左侧右侧都被墙壁堵住,并且太近 if (vecTarget == Vector3.zero) { if (Utility.CameraCanLookTarget(UnitTarget, newViewIndex[2], out wallHitPos)) { vecTarget = newViewIndex[2]; } else { vecTarget = wallHitPos; } } newPos = vecTarget; //整个视角都是缓动的 Vector3 velocity = currentVelocity; transform.position = Vector3.SmoothDamp(transform.position, newPos, ref velocity, SmoothDampTime); currentVelocity = velocity; //摄像机朝向观察目标,平滑的旋转视角 Quaternion to = Quaternion.LookRotation(CameraLookAt.position - transform.position, Vector3.up); transform.rotation = Quaternion.Lerp(transform.rotation, to, SmoothDampTime); } else { if (xRotate != 0.0f) { //根据参数调整高度,和距离. //最高俯仰75度。 lastAngle -= xRotate;//鼠标往上,是仰视,往下是俯视 if (lastAngle >= angleMax) { lastAngle = angleMax; followDistance = Mathf.Abs((fRadis * Mathf.Cos(lastAngle * Mathf.Deg2Rad))); followHeight = Mathf.Abs((fRadis * Mathf.Sin(lastAngle * Mathf.Deg2Rad))); } else if (lastAngle <= angleMin) { lastAngle = angleMin; followDistance = Mathf.Abs((fRadis * Mathf.Cos(lastAngle * Mathf.Deg2Rad))); followHeight = -Mathf.Abs((fRadis * Mathf.Sin(lastAngle * Mathf.Deg2Rad))); } else { followDistance = Mathf.Abs((fRadis * Mathf.Cos(lastAngle * Mathf.Deg2Rad))); followHeight = lastAngle == 0.0f ? 0 : (lastAngle / Mathf.Abs(lastAngle)) * Mathf.Abs((fRadis * Mathf.Sin(lastAngle * Mathf.Deg2Rad))); } } newPos.x = Target.transform.position.x; newPos.y = Target.position.y + BodyHeight + followHeight; newPos.z = Target.transform.position.z; newPos += Main.Ins.LocalPlayer.transform.forward * followDistance; vecTarget.x = Target.position.x; vecTarget.y = Target.position.y + BodyHeight; vecTarget.z = Target.position.z; //如果新的位置,与目标注视点中间隔着墙壁 RaycastHit wallHit; bool hitWall = false; if (Physics.Linecast(CameraLookAt.position, newPos, out wallHit, LayerManager.AllSceneMask)) { hitWall = true; SceneItemAgent item = wallHit.collider.gameObject.GetComponentInParent <SceneItemAgent>(); if (item != null) { //不需要移动相机的位置 if (occlusionItem != null) { if (item != occlusionItem) { occlusionItem.RestoreAlpha(); occlusionItem = item; occlusionItem.SetAlpha(0.3f); } } else { occlusionItem = item; item.SetAlpha(0.3f); } } else { float dis = Vector3.Distance(CameraLookAt.position, wallHit.point); newPos = wallHit.point + Vector3.Normalize(CameraLookAt.position - wallHit.point) * 5; } } else { if (occlusionItem != null) { occlusionItem.RestoreAlpha(); occlusionItem = null; } } //没有撞墙 if (!hitWall) { newPos.x = Target.transform.position.x; newPos.z = Target.transform.position.z; float y = Mathf.SmoothDamp(CameraPosition.position.y, newPos.y, ref currentVelocityY, f_DampTime / 2); newPos.y = y; newPos += Main.Ins.LocalPlayer.transform.forward * followDistance; } else { float y = Mathf.SmoothDamp(CameraPosition.position.y, newPos.y, ref currentVelocityY, f_DampTime / 2); newPos.y = y; } CameraPosition.position = newPos; vecTarget.x = Target.position.x; vecTarget.y = Mathf.SmoothDamp(CameraLookAt.position.y, Target.position.y + BodyHeight, ref currentVelocityY2, f_DampTime / 2); vecTarget.z = Target.position.z; CameraLookAt.position = vecTarget; //由电影视角,切换到单人视角之间的动画. if (animationPlay) { if (animationTick >= SmoothDampTime) { animationTick = 0.0f; animationPlay = false; } else { //当锁定目标丢失,或者死亡时.从双人视角转换为单人视角的摄像机过渡动画. animationTick += FrameReplay.deltaTime; Vector3 velocity = currentVelocity; transform.position = Vector3.SmoothDamp(transform.position, newPos, ref velocity, SmoothDampTime, f_speedMax); currentVelocity = velocity; Quaternion to = Quaternion.LookRotation(CameraLookAt.position - transform.position, Vector3.up); transform.rotation = Quaternion.Lerp(transform.rotation, to, SmoothDampTime); return; } } else { transform.position = CameraPosition.position; transform.LookAt(CameraLookAt.position, Vector3.up); } } }