在玩ARPG手游的时候,我们常常会发现在战斗的过程中,如果有怪物在屏幕的外边(即玩家视野之外)的时候,会发现在玩家周围活屏幕边缘有指示怪物方位的箭头,而且这是在UI上的。我用UGUI来实现这个贴心的功能。

首先实现思路:肯定是把3D世界的坐标投射到屏幕坐标,再由屏幕坐标投射到UI坐标。有两种实现方式:

  1. 先在3D世界中把指示箭头的位置计算出来。

然后再把计算出来的点投射到屏幕。与玩家的点也投射到屏幕。

2.把玩家的位置和怪物的世界坐标分别投射至UI坐标,然后在UI坐标里计算出指示箭头的位置。这样指示箭头与玩家的距离稳定。这种方案理论上是没问题的,但实际实现的过程中,我发现角色走到某些地方(怪物距离屏幕很远的地方)的时候发现指示箭头反向了,并不对。发现是
Camera.WorldToScreenPoint这个方法得出的屏幕坐标有问题,原因不明啊。

实现之:
涉及到的知识点:
- 把世界坐标投射到屏幕坐标,及把屏幕坐标投射到UI(用了单独的摄像机来渲染UI)坐标。
- 向量的基本计算。
- UI里设置图片旋转到指定方向(即UI的LookAt)。
- 怪物是否在屏幕里的判断

准备:

写代码:

using UnityEngine;
using System.Collections.Generic;
using UnityEngine.UI;
/// <summary>
/// 怪物位置指示器
/// </summary>
public class MonsterIndicator : MonoBehaviour
{//public List<Transform> monsterList;public Transform player;public int disFromPlayer = 200;//指示箭头与玩家距离,以像素算public Camera uiCam;List<Transform> indicatorList = new List<Transform>();//指示箭头图片资源Dictionary<int, IndicatorMonster> outScreenMonsters = new Dictionary<int, IndicatorMonster>();//在屏幕外的怪物列表void Start(){for (int i = 0, size = transform.childCount; i < size; i++){Transform child = transform.GetChild(i);indicatorList.Add(child);child.name = "-1";}}void LateUpdate(){foreach (KeyValuePair<int, IndicatorMonster> kv in outScreenMonsters){kv.Value.Update();}}int GetNoUseIndicator(){for (int i = 0, size = indicatorList.Count; i < size; i++){if (indicatorList[i].name.CompareTo("-1") == 0) return i;}Transform indicator = Instantiate<Transform>(indicatorList[0]);indicator.SetParent(indicatorList[0].parent);indicator.localScale = Vector3.one;indicator.name = "-1";indicatorList.Add(indicator);return indicatorList.Count - 1;}public void OnScreen(bool outScreen, Transform monst){int key = monst.GetInstanceID();if (outScreen){if (!outScreenMonsters.ContainsKey(key)){IndicatorMonster monstInfo = new IndicatorMonster();monstInfo.monst = monst;Transform indicator = indicatorList[GetNoUseIndicator()];indicator.name = key.ToString();indicator.gameObject.SetActive(true);monstInfo.indicator = indicator;monstInfo.player = player;monstInfo.uiCam = uiCam;monstInfo.parent = transform as RectTransform;monstInfo.disFromPlayer = disFromPlayer;outScreenMonsters.Add(key, monstInfo);}}else{if (outScreenMonsters.ContainsKey(key)){outScreenMonsters[key].Dispose();outScreenMonsters.Remove(key);}}}}internal class IndicatorMonster
{public Transform indicator;public Transform monst;public Transform player;public Camera uiCam;public RectTransform parent;public int disFromPlayer;public void Update(){Vector3 indicatorPoint = (monst.position - player.position).normalized * 5 + player.position;Vector3 indicatorScnPoint = Camera.main.WorldToScreenPoint(indicatorPoint);Vector3 playerPos = Camera.main.WorldToScreenPoint(player.position);Vector2 indicatorUIPoint;Vector2 playerUIPos;RectTransformUtility.ScreenPointToLocalPointInRectangle(parent, indicatorScnPoint, uiCam, out indicatorUIPoint);RectTransformUtility.ScreenPointToLocalPointInRectangle(parent, playerPos, uiCam, out playerUIPos);Vector2 indicatorPos = playerUIPos + (indicatorUIPoint - playerUIPos).normalized * 200;indicator.localPosition = new Vector3(indicatorPos.x, indicatorPos.y, 0);UILookAt(indicator, indicatorUIPoint - playerUIPos, Vector3.up);}/// <summary>/// UI的LookAt/// </summary>/// <param name="transform"></param>/// <param name="dir"></param>/// <param name="lookAxis"></param>public void UILookAt(Transform transform, Vector3 dir, Vector3 lookAxis){Quaternion q = Quaternion.identity;q.SetFromToRotation(lookAxis, dir);transform.rotation = q;} public void Dispose(){indicator.gameObject.SetActive(false);indicator.gameObject.name = "-1";indicator = null;monst = null;player = null;uiCam = null;parent = null;}
}

效果:

UGUI 实现屏幕外怪物的指示箭头相关推荐

  1. WIN10运行软件,窗口不显示(移动到屏幕外无法复原)的解决办法 Label:Win10解决方案

    WIN10运行软件,窗口不显示(移动到屏幕外无法复原)的解决办法 Label:Win10解决方案 参考文章: (1)WIN10运行软件,窗口不显示(移动到屏幕外无法复原)的解决办法 Label:Win ...

  2. java菜单面板设置完能关闭_用Java创建一个屏幕外框架(或者:当所有应用程序窗口关闭时,如何避免Mac上的空白菜单)?...

    你一定要考虑WizardOfOdds非常有用的答案.正确使用 "The Application Menu"将有所帮助,并且很容易设置最小的 Info.plist开始.持久的文件菜单 ...

  3. windows窗口移动到屏幕外,找回方法

    windows窗口移动到屏幕外,找回方法 1.将应用程序切换到激活状态:alt + tab 切换到应用程序 或 鼠标点任务栏(激活状态) 2.alt + 空格键(激活菜单) 3.alt + m (移动 ...

  4. CSS实现空心三角指示箭头

    web开发中,三角形的日常应用,以三角形指示箭头最为常见,其用CSS来实现非常简单,熟悉了之后相比于引入SVG或是背景图片会是更好更灵活的选择. 而三角箭头一般而言,又分为两种,一种是视觉上没有边框的 ...

  5. android实现箭头流程列表_Android下拉列表选项框及指示箭头动画

    android原生的Spinner提供了下拉列表选项框,但在一些流行的APP中,原生的Spinner似乎不太受待见,而通常会有下图所示的下拉列表选项框: 初始化状态: 点击弹出下拉选择选项框: 选中后 ...

  6. html上下箭头动态效果,使用CSS和Bootstrap图标制作上下跳动的指示箭头动画效果...

    有时侯页面很长,需要指示箭头告诉用户下面还有东西.可以用纯CSS的方法实现. HTML:添加一个链接,可修改锚点点击时滑动到指定位置,这里使用了Bootstrap 3.x版本的一个向下箭头作为图标. ...

  7. html怎么做向下的图标,用CSS和Bootstrap图标制作上下跳动的指示箭头动画效果

    有时侯页面很长,需要指示箭头告诉用户下面还有东西.可以用纯CSS的方法实现. HTML:添加一个链接,可修改锚点点击时滑动到指定位置,这里使用了Bootstrap 3.x版本的一个向下箭头作为图标. ...

  8. css 让图标上下跳,使用CSS和Bootstrap图标制作上下跳动的指示箭头动画效果

    有时侯页面很长,需要指示箭头告诉用户下面还有东西.可以用纯CSS的方法实现. HTML:添加一个链接,可修改锚点点击时滑动到指定位置,这里使用了Bootstrap 3.x版本的一个向下箭头作为图标. ...

  9. Android弹出选项框及指示箭头动画选择

     Android弹出选项框及指示箭头动画选择 Android原生的Spinner提供了下拉列表选项框,但在一些流行的APP中,原生的Spinner似乎不太受待见,而通常会有下图所示的下拉列表选项框 ...

  10. 游戏屏幕外渲染黑屏_看Nintendos在屏幕外的精灵渲染故障

    游戏屏幕外渲染黑屏 While I was capturing some game footage from Zelda II, I noticed a strange little glitch. ...

最新文章

  1. 工欲善其事,必先利其器。如何玩转 VS Code?
  2. SHELL-命令解释程序
  3. pyplot绘图标题错误处理
  4. egg mysql 项目实战,egg.js创建项目,目录介绍,简单使用,sequelize mysql使用
  5. 图像滤波之高斯滤波介绍
  6. java 程序是由什么组成的 java_从零开始的JAVA -2. java程序的构成及命名规则
  7. scrum master_从Scrum Master到工程副总裁:职称为何重要
  8. 预见2021:《2021年中国呼叫中心产业全景图谱》 未来十年八大预测
  9. 以后别写程序了,几个程序员很有用的源码网站奉献给大家
  10. hadoop服务器的配置文件在哪,Hadoop配置文件详解、安装及相关操作
  11. 冒险者传说pc6java_我的世界之冒险者传说整合包游戏
  12. 游戏加速外挂分析以及制作
  13. 电磁兼容学习-电磁干扰三要素
  14. 【计算机组成】内存和芯片存储容量问题
  15. 关于library cache lock
  16. 使用adb.exe禁止安卓手机app震动权限
  17. python科学计算环境配置_ATLAS + NumPy + SciPy + Theano 的Python科学计算环境搭建
  18. networkx读取gml文件失败
  19. 淘宝直通车选词怎么做?大神导航,一个神奇的网站,从此开启大神之路!
  20. CAS流程简析 服务端校验Ticket

热门文章

  1. 一人顶一个团队的华为天才少年稚晖君,又带来一项硬核黑科技,引起极客圈地震!...
  2. 图解Navicat连接、操作数据库
  3. 【HTML 教程系列第 4 篇】HTML 的注释怎么写?
  4. google地图距离算法_谷歌地图计算两个坐标点的距离函数
  5. MYSQL 数据库维护常识
  6. 华为防火墙默认密码是什么?
  7. 个人空间岁末大回报活动12月23日获奖名单
  8. CSS盒子模型居中方法,高级面试题+解析
  9. java实现excel 行列转置,行列转换。附完整代码
  10. 在COMSOL中固体力学模块中添加 力矩 扭矩