# TPS相机及相机遮挡的一些处理方法

15-11-08        来源：[db:作者]

### 控制思路

```transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0);

characterModel.transform.forward = new Vector3(transform.forward.x, characterModel.transform.forward.y, transform.forward.z);
target.forward = new Vector3(transform.forward.x, 0, transform.forward.z);

float yaw = rotationX;
float pitch = rotationY;
float yawRed = Mathf.Deg2Rad * (yaw - 90f);
float pitchRed = Mathf.Deg2Rad * pitch;
Vector3 direction = new Vector3(-Mathf.Cos(yawRed) * Mathf.Cos(pitchRed), -Mathf.Sin(pitchRed), Mathf.Sin(yawRed) * Mathf.Cos(pitchRed));

transform.position = target.transform.position + distance * direction;
transform.position += transform.right + transform.up;```

direction是通过yaw和pitch计算出的角色到相机的Ray的方向。

### 一些问题的处理

```	characterModel.transform.forward = new Vector3(transform.forward.x, characterModel.transform.forward.y, transform.forward.z);
if (characterModel.transform.parent.GetComponent().characterFPAnimation.extraRotation == 0)
{
extraRot = Mathf.Lerp(extraRot, 0f, 10 * Time.deltaTime);
}else
{
extraRot = Mathf.Lerp(extraRot, characterModel.transform.parent.GetComponent().characterFPAnimation.extraRotation, 10 * Time.deltaTime);
}
Quaternion targetRotation = characterModel.transform.rotation * Quaternion.AngleAxis(extraRot, Vector3.up);

characterModel.transform.rotation = targetRotation;```

``` bool ViewingPosCheck (Vector3 checkPos)
{
RaycastHit hit;

// If a raycast from the check position to the player hits something...
if(Physics.Raycast(checkPos, player.position - checkPos, out hit, relCameraPosMag))
// ... if it is not the player...
if(hit.transform != player)
// This position isn't appropriate.
return false;

// If we haven't hit anything or we've hit the player, this is an appropriate position.
newPos = checkPos;
return true;
}

void SmoothLookAt ()
{
// Create a vector from the camera towards the player.
Vector3 relPlayerPosition = player.position - transform.position;

// Create a rotation based on the relative position of the player being the forward vector.
Quaternion lookAtRotation = Quaternion.LookRotation(relPlayerPosition, Vector3.up);

// Lerp the camera's rotation between it's current rotation and the rotation that looks at the player.
transform.rotation = Quaternion.Lerp(transform.rotation, lookAtRotation, smooth * Time.deltaTime);
}```

```  void FixedUpdate ()
{
// The standard position of the camera is the relative position of the camera from the player.
Vector3 standardPos = player.position + relCameraPos;

// The abovePos is directly above the player at the same distance as the standard position.
Vector3 abovePos = player.position + Vector3.up * relCameraPosMag;

// An array of 5 points to check if the camera can see the player.
Vector3[] checkPoints = new Vector3[5];

// The first is the standard position of the camera.
checkPoints[0] = standardPos;

// The next three are 25%, 50% and 75% of the distance between the standard position and abovePos.
checkPoints[1] = Vector3.Lerp(standardPos, abovePos, 0.25f);
checkPoints[2] = Vector3.Lerp(standardPos, abovePos, 0.5f);
checkPoints[3] = Vector3.Lerp(standardPos, abovePos, 0.75f);

// The last is the abovePos.
checkPoints[4] = abovePos;

// Run through the check points...
for(int i = 0; i < checkPoints.Length; i++)
{
// ... if the camera can see the player...
if(ViewingPosCheck(checkPoints[i]))
// ... break from the loop.
break;
}

// Lerp the camera's position between it's current position and it's new position.
transform.position = Vector3.Lerp(transform.position, newPos, smooth * Time.deltaTime);

// Make sure the camera is looking at the player.
SmoothLookAt();
}```

```void ShelterTest()
{
RaycastResult result = new RaycastResult();
float characterHeight = GameManager.GetInstance().character.height * 0.4f;
Vector3 targetHeadPos = new Vector3(target.position.x, target.position.y + characterHeight, target.position.z);

Ray[] testRays = new Ray[5];
testRays[0] = new Ray(targetHeadPos, transform.position + 0.8f * transform.right + 0.5f * transform.up - targetHeadPos);
testRays[1] = new Ray(targetHeadPos, transform.position + 0.8f * transform.right - 0.5f * transform.up - targetHeadPos);
testRays[2] = new Ray(targetHeadPos, transform.position - 0.8f * transform.right + 0.5f * transform.up - targetHeadPos);
testRays[3] = new Ray(targetHeadPos, transform.position - 0.8f * transform.right - 0.5f * transform.up - targetHeadPos);

testRays[4] = new Ray(transform.position, transform.position - targetHeadPos);

float castDist = (transform.position - targetHeadPos).magnitude;
float[] dists = new float[5];
for (int i = 0; i < 5; i++)
{
if (RaycastHelper.RaycastAll(testRays[i], castDist, true, GameManager.GetInstance().character.floorMask, out result))
{
}else
{
dists[i] = castDist;
}
}

float minDist0 = Mathf.Min(dists[0], dists[1]);
float minDist1 = Mathf.Min(dists[2], dists[3]);
float minDist2 = Mathf.Min(minDist0, minDist1);
float minDist = Mathf.Min(minDist2, dists[4]);

transform.position = targetHeadPos + minDist * testRays[4].direction.normalized;

}```

```Shader Custom/Player {

Properties {
_MainTex (Base (RGB), 2D) = white {}
}

Tags { RenderType=Opaque }
LOD 200

Stencil {
Comp always
Pass replace
ZFail keep
}

CGPROGRAM
#pragma surface surf Lambert

sampler2D _MainTex;

struct Input {
float2 uv_MainTex;
};

void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = c.rgb;
o.Alpha = c.a;
}
ENDCG
}
FallBack Diffuse
}
```

```Shader Custom/ClearZbuffer {
Properties {
_MainTex (Base (RGB) Gloss (A), 2D) = white {}
}
Tags { RenderType=Transparent  Queue=Transparent+100}
LOD 80
ZTest Greater
ZWrite On

CGPROGRAM
#pragma surface surf Lambert

sampler2D _MainTex;

struct Input {
float2 uv_MainTex;
};

void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex);
o.Albedo = half4(1,0,0,1);
o.Alpha = 0.3;
}
ENDCG
}
FallBack Diffuse
}
```

```Shader Custom/StencilTransparent {
Properties {
_MainTex (Base (RGB), 2D) = white {}
_TransVal (Transparency Value, Range(0,1)) = 1.0
}
Tags { RenderType=Opaque Queue=Transparent+100}
LOD 80

Stencil {
Comp notequal
Pass keep
}

ZTest LEqual
ZWrite On
Blend SrcAlpha OneMinusSrcAlpha

CGPROGRAM
#pragma surface surf Lambert

sampler2D _MainTex;
fixed _TransVal;

struct Input {
float2 uv_MainTex;
};

void surf (Input IN, inout SurfaceOutput o) {
half4 c = tex2D (_MainTex, IN.uv_MainTex);
//o.Albedo = c.rgb * half4(1,0,0,1);
//o.Alpha = 1;
o.Alpha = _TransVal;
}
ENDCG
}
FallBack Diffuse
}
```