首先我们都知道用Camera.main.WorldToScreenPoint(),这是目的地在屏幕内的情况。
- 如果在屏幕外但还在玩家前方,对坐标的xy使用Mathf.Clamp()限制到屏幕里就行。
- 如果目的地在玩家后方,我选择根据是偏左还是偏右粗暴的放到屏幕最左或最右;
注意WorldToScreenPoint()的结果受屏幕分辨率影响,分辨率1920*1080和16:9 Aspect的效果不一样。所以加上pos.x * canvasRT.width / Screen.width消除影响。
简单粗暴的方法
注意z<0也就是在玩家身后时,x>Screen.width / 2反而意味着偏左。
cs
void GetMarkerPos()
{
Vector3 pos=Camera.main.WorldToScreenPoint(chasingMission.transform.position);
if (pos.z > 0)
{
pos.x = Mathf.Clamp(pos.x,0, Screen.width);
pos.y = Mathf.Clamp(pos.y,0, Screen.height);
}
else {
pos.x = pos.x < Screen.width / 2 ? Screen.width : 0;
pos.y=Screen.height / 2;
}
pos = new Vector2(pos.x * canvasRT.width / Screen.width,
pos.y * canvasRT.height/Screen.height);
string distanceHint = ((int)Vector3.Distance(player.transform.position,
chasingMission.transform.position)).ToString() + "m";
onUpdateMarker?.Invoke(pos, distanceHint);
}
一个之前的方法,很麻烦
cs
Rect scale;
void Start(){
Rect screen = (GameSceneManager.Instance.canvas.transform as RectTransform).rect;
//画布的rect宽高固定为1920*1080,即使分辨率只是自由16:9
scale.width = screen.width / Screen.width;
scale.height = screen.height / Screen.height;
}
void CalculateMissionMarkerPosition(){
targetDir=targetMission.transform.position-player.transform.position;
if(Vector3.Angle(player.transform.forward,targetDir)<Camera.main.fieldOfView){
Vector2 pos=Camera.main.WorldToScreenPoint(targetMission.transform.position);
pos = new Vector2(pos.x / Screen.width * 1920, pos.y / Screen.height * 1080);
missionMarker.anchoredPosition=pos;
}
else{
if(cinemachineBrain.ActiveVirtualCamera==null){
return;//在第一帧可能ActiveVirtualCamera是空
}
Vector3 destInPlayer=cinemachineBrain.ActiveVirtualCamera.VirtualCameraGameObject.
transform.InverseTransformPoint(targetMission.transform.position);
Vector2 pos;
if(Mathf.Abs(destInPlayer.y/destInPlayer.x)>(float)Screen.height/Screen.width){
pos.x=Mathf.Abs(destInPlayer.x/destInPlayer.y*Screen.height/2);
if(destInPlayer.x<0){
pos.x=-pos.x;
}
if(destInPlayer.y>0){
pos.y=Screen.height/2;
}
else{
pos.y=-Screen.height/2;
}
}
else{
pos.y=Mathf.Abs(destInPlayer.y/destInPlayer.x*Screen.width/2);
if(destInPlayer.y<0){
pos.y=-pos.y;
}
if(destInPlayer.x>0){
pos.x=Screen.width/2;
}
else{
pos.x=-Screen.width/2;
}
}
missionMarker.anchoredPosition=pos+new Vector2(Screen.width,Screen.height)/2;
}
textDistance.text = ((int)Vector3.Distance(MyInput.Instance.player.transform.position,
targetMission.transform.position)).ToString()+"m";
}