开发手札:CameraRTS精准性优化

      虽然三维软件提供了基本的物体RTS操作,但是对于用户来说过于复杂。
      这些操作方式需要用户理解什么是三维空间、XYZ坐标系、欧拉角等。但是用户视角下,就一个二维屏幕+动来动去的鼠标光标。
      之前写过一套RTM组件,RTM组件,讲解了移动操作。
      这次基于Camera视口(二维屏幕)+屏幕坐标(鼠标光标)来实现一套全新的物体RTS操作。
      一.Translate
      移动的原理是根据RayHitPoint获取视椎平面,使物体在视椎平面相对移动,如下:
在这里插入图片描述

      根据hitpointhp1的相对坐标计算centerc1的坐标
      接下来实现代码:

using UnityEngine;
using UnityEngine.EventSystems;public abstract class RTSBaseComp : MonoBehaviour
{public bool isOperating = false;protected Vector3 rayHitPoint;          //交点protected Vector3 worldBaisPos;         //世界坐标偏移量protected float planeDistance;          //交点平面距离protected virtual void Awake(){}protected virtual void Start(){EventTriggerListener.Get(gameObject).onLeftPointDown.AddListener(LeftPointDownCallback);EventTriggerListener.Get(gameObject).onLeftPointUp.AddListener(LeftPointUpCallback);}protected virtual void Update(){}protected virtual void LeftPointDownCallback(GameObject go, PointerEventData data){if (CameraControl.Instance.IsPointRaycastHit(out var rayhit)){rayHitPoint = rayhit.point;worldBaisPos = transform.position - rayHitPoint;planeDistance = CameraControl.Instance.GetParallelPlaneDistance(rayHitPoint);isOperating = true;}}protected virtual void LeftPointUpCallback(GameObject go, PointerEventData data){isOperating = false;}protected virtual void OnDestroy(){EventTriggerListener.Get(gameObject).onLeftPointDown.RemoveListener(LeftPointDownCallback);EventTriggerListener.Get(gameObject).onLeftPointUp.RemoveListener(LeftPointUpCallback);}
}

      基类中封装最基本的用户鼠标操作。

/// <summary>
/// 根据世界坐标获取平行于视锥体平面
/// 获取平面距离
/// </summary>
/// <param name="screenPos"></param>
/// <param name="wpos"></param>
/// <returns></returns>
public float GetParallelPlaneDistance(Vector3 wpos)
{Vector3 from = mainTransform.position;Vector3 end = wpos;Vector3 f2e = end - from;float f2eDistance = Vector3.Distance(from, end);float deg = Vector3.Angle(f2e, mainTransform.forward);float pdistance = Mathf.Cos(deg * Mathf.Deg2Rad) * f2eDistance;return pdistance;
}
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;/// <summary>
/// 基于HitPoint视锥平面
/// </summary>
public class RTSTranslateComp : RTSBaseComp
{public UnityAction<Vector3> OnTranslatingListener;public UnityAction<Vector3> OnEndTranslateListener;protected override void Update(){base.Update();if (isOperating){Vector2 csPos = new Vector2(Input.mousePosition.x, Input.mousePosition.y);Vector3 cwPos = CameraControl.Instance.GetScreenToWorldPos(csPos, planeDistance);transform.position = cwPos + worldBaisPos;OnTranslatingListener?.Invoke(transform.position);}}protected override void LeftPointUpCallback(GameObject go, PointerEventData data){base.LeftPointUpCallback(go, data);OnEndTranslateListener?.Invoke(transform.position);}
}

      PS:其中有一些依赖函数是我框架代码内的,只标注意义,因为以前都有讲解过原理,所以节省篇幅。
      效果如下:
在这里插入图片描述
      二.Rotate
      旋转的原理是根据RayHitPoint获取视椎平面Plane。物体中心到Plane投影点为旋转中心,Camera坐标系为基准。HitPoint绕Z轴旋转,依据左手定则,如下:
在这里插入图片描述
      需要注意的是基于RayHitPoint视椎平面的旋转。
      接下来实现代码:

using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;/// <summary>
/// 基于RayHitPoint视锥平面
/// </summary>
public class RTSRotateComp : RTSBaseComp
{public UnityAction<Vector3> OnRotatingListener;public UnityAction<Vector3> OnEndRotateListener;private Vector3 rotateAxis;             //旋转轴private Vector3 rotateCenter;           //旋转中心private Vector3 lastHitPoint;private Vector3 crtHitPoint;protected override void LeftPointDownCallback(GameObject go, PointerEventData data){base.LeftPointDownCallback(go, data);rotateAxis = CameraControl.Instance.mainTransform.forward;Vector2 csPos = CameraControl.Instance.GetWorldToScreenPos(transform.position);rotateCenter = CameraControl.Instance.GetScreenToWorldPos(csPos, planeDistance);lastHitPoint = rayHitPoint;}protected override void Update(){base.Update();#if UNITY_EDITOR//辅助坐标系Debug.DrawLine(rotateCenter, rotateCenter + CameraControl.Instance.mainTransform.right, Color.red);Debug.DrawLine(rotateCenter, rotateCenter + CameraControl.Instance.mainTransform.up, Color.green);Debug.DrawLine(rotateCenter, rotateCenter + rotateAxis, Color.blue);
#endifif (isOperating){crtHitPoint = CameraControl.Instance.GetScreenToWorldPos(Input.mousePosition, planeDistance);Vector3 f = lastHitPoint - rotateCenter;Vector3 t = crtHitPoint - rotateCenter;//f到t的角度,左手定则,逆时针float deltaAngle = Vector3.SignedAngle(f, t, rotateAxis);transform.RotateAround(rotateCenter, rotateAxis, deltaAngle);lastHitPoint = crtHitPoint;OnRotatingListener?.Invoke(transform.eulerAngles);}}protected override void LeftPointUpCallback(GameObject go, PointerEventData data){base.LeftPointUpCallback(go, data);OnEndRotateListener?.Invoke(transform.eulerAngles);}}

      效果如下:
在这里插入图片描述

      三.Scale
      常见的缩放功能是鼠标滚轮缩放物体,但是并非基于RayHitPoint,所以视觉上会偏移,为了修正偏移,实现基于RayHitPoint的缩放。
      原理是在缩放的同时,根据RayHitPoint相对位移计算物体中心位移,依据视椎平面相对位移*相对缩放即可。如下:

在这里插入图片描述

      代码实现如下:

using UnityEngine;
using UnityEngine.EventSystems;public class RTSScaleComp : MonoBehaviour
{[Range(0.5f, 2f)]public float ScrollSpeed = 1.0f;private bool isPointEnter = false;private Vector3 rayHitPoint;            //交点private Vector3 lastLocalScale;         //当前缩放值private Vector3 worldBaisPos;           //世界坐标偏移量private float planeDistance;            //交点平面距离privatevoid Start(){EventTriggerListener.Get(gameObject).onPointEnter.AddListener(PointEnterCallback);EventTriggerListener.Get(gameObject).onPointExit.AddListener(PointExitCallback);}private void PointEnterCallback(GameObject go, PointerEventData data){isPointEnter = true;}private void PointExitCallback(GameObject go, PointerEventData data){isPointEnter = false;}void Update(){if (isPointEnter){float val = Input.GetAxis("Mouse ScrollWheel");if (val == 0){if (CameraControl.Instance.IsPointRaycastHit(out var rayhit)){rayHitPoint = rayhit.point;worldBaisPos = transform.position - rayHitPoint;lastLocalScale = transform.localScale;planeDistance = CameraControl.Instance.GetParallelPlaneDistance(rayHitPoint);}}else{ScrollMove(val);Vector2 csPos = new Vector2(Input.mousePosition.x, Input.mousePosition.y);Vector3 cwPos = CameraControl.Instance.GetScreenToWorldPos(csPos, planeDistance);//计算缩放Vector3 sca = transform.localScale.Division(lastLocalScale);transform.position = cwPos + worldBaisPos.Multiply(sca);}}}public void ScrollMove(float val){transform.localScale += (Vector3.one * val * ScrollSpeed);}private void OnDestroy(){EventTriggerListener.Get(gameObject).onPointEnter.RemoveListener(PointEnterCallback);EventTriggerListener.Get(gameObject).onPointExit.RemoveListener(PointExitCallback);}
}

      效果如下:
在这里插入图片描述

      这样就实现了一套Camera(用户)视角下,精准的RTS操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/494444.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

高级的SQL查询技巧有哪些?

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///C爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于高级SQL查询技巧方面的相关内容&#xf…

helm的介绍和安装

1 helm概述 1.1 资源对象难以管理的问题 helm是k8s资源清单的管理工具&#xff0c;它就像Linux下的包管理器&#xff0c;比如centos的yum&#xff0c;ubuntu的apt helm&#xff1a;命令行工具&#xff0c;主要用于k8s的chart的创建&#xff0c;打包&#xff0c;发布和管理。…

专业的内外网数据交换方案 可解决安全、效率、便捷3大问题

内外网数据交换是很多企业和行业都会面临的场景&#xff0c;既然隔离了内外网&#xff0c;重中之重就是要确保数据的安全性&#xff0c;其次在数据流转交换过程中&#xff0c;不能太繁琐复杂&#xff0c;需要让用户快速、便捷的进行数据交换。首先我们来看看&#xff0c;在进行…

2024 楚慧杯 re wp

go_bytes 附件拖入ida 输入长度为0x28&#xff0c;每两位字符的4bit拼接 与一个常量值经过运算后的值进行异或&#xff0c;并且判断是否相等 脚本 bouquet 附件拖入ida。简单去一下花 构建了一个二叉树&#xff0c;然后递归调用函数 重新排列一下再层序遍历读出即可 zistel 附件…

BERT模型入门(1)BERT的基本概念

文章目录 BERT是Bidirectional Encoder Representations from Transformers的首字母简写&#xff0c;中文意思是&#xff1a;Transformer的双向编码器表示。它是谷歌发布的最先进的嵌入模型。BERT在许多NLP任务中提供了更好的结果&#xff0c;如问答、文本生成、句子分类等&…

ECharts关系图-关系图11,附视频讲解与代码下载

引言&#xff1a; 关系图&#xff08;或称网络图、关系网络图&#xff09;在数据可视化中扮演着至关重要的角色。它们通过节点&#xff08;代表实体&#xff0c;如人、物体、概念等&#xff09;和边&#xff08;代表实体之间的关系或连接&#xff09;的形式&#xff0c;直观地…

java全栈day19--Web后端实战(java操作数据库3)

一、MyBatis 1.1介绍 前提引入&#xff1a; controller(控制层)作用&#xff1a;接受请求&#xff0c;响应数据 service(业务层)作用&#xff1a;负责具体的逻辑处理 dao(持久层)作用&#xff1a;数据访问层 一般的访问流程&#xff1a;浏览器发起请求过来&#xff0c;先…

Hmsc包开展群落数据联合物种分布模型分析通用流程(Pipelines)

HMSC&#xff08;Hierarchical Species Distribution Models&#xff09;是一种用于预测物种分布的统计模型。它在群落生态学中的应用广泛&#xff0c;可以帮助科学家研究物种在不同环境条件下的分布规律&#xff0c;以及预测物种在未来环境变化下的潜在分布范围。 举例来说&a…

PostgreSQL 的历史

title: PostgreSQL 的历史 date: 2024/12/23 updated: 2024/12/23 author: cmdragon excerpt: PostgreSQL 是一款功能强大且广泛使用的开源关系型数据库管理系统。其历史可以追溯到1986年,当时由加州大学伯克利分校的一个研究团队开发。文章将深入探讨 PostgreSQL 的起源、…

CSPM认证最推荐学习哪个级别?

一、什么是CSPM&#xff1f; CSPM的全称是Certified Strategic Project Manager&#xff0c;中文名称为“项目管理专业人员能力评价等级证书”。这是由中国标准化协会依据国家标准《项目管理专业人员能力评价要求》&#xff08;GB/T 41831-2022&#xff09;推出的一项认证&…

车载网关性能 --- GW ECU报文(message)处理机制的技术解析

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所谓鸡汤,要么蛊惑你认命,要么怂恿你拼命,但都是回避问题的根源,以现象替代逻辑,以情绪代替思考,把消极接受现实的懦弱,伪装成乐观面对不幸的…

IT运维的365天--021 服务器上的dns设置后不起作用

之前在内网搭建了一个和外网同域名的网站&#xff0c;开发同事今天告诉我&#xff0c;程序调试发现可能服务器不能正常访问自己内网的网站内容。于是&#xff0c;今天的故事开始了。 前面的文章在下面列出&#xff0c;当然不看也问题不大&#xff0c;今天的主题是&#xff1a;…

任务2 配置防火墙firewalld

基本概念 概述 支持动态更新防火墙规则 不重启即可创建、修改和删除规则 使用区域和服务来简化防火墙配置 区域 一组预定义的规则&#xff0c;防火墙策略集合&#xff08;或策略模板&#xff09; 把网络分配到不同的区域中&#xff0c;并为网络及其关联的网络接口或流量源…

FPGA(一)verilog语句基础

Verilog 是一种硬件描述语言&#xff08;HDL&#xff09;&#xff0c;常用于数字电路的设计、模拟和验证&#xff0c;特别是用于 FPGA 和 ASIC 的设计。Verilog 让设计者能够描述和模拟硬件系统的行为和结构&#xff0c;最终将其转化为硬件电路。 一、模块结构 Verilog 中的设计…

Asp.Net FrameWork 4.7.2 WebAPI 使用WebSocket协议

参考文章&#xff1a;Asp.net webApi 通过WebSocket推送消息给客户端&#xff0c;搭建一个即是服务端又是客户端的服务_c# webapi websocket-CSDN博客 WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455&#xff0c;并由…

网关的国际化改造

网关的国际化改造和web服务的改造有所不同。 问题 SpringCloud Gateway是基于reactor模型的&#xff0c;按照SpringBoot那套以及所尝试网上以及AI的i18n国际化方案&#xff0c;都没有成功。 解决问题 基本思路跟SpringBoot项目的i18n一样 通过MessageSource加载messages国际…

数据分析思维(五):分析方法——假设检验分析方法

数据分析并非只是简单的数据分析工具三板斧——Excel、SQL、Python&#xff0c;更重要的是数据分析思维。没有数据分析思维和业务知识&#xff0c;就算拿到一堆数据&#xff0c;也不知道如何下手。 推荐书本《数据分析思维——分析方法和业务知识》&#xff0c;本文内容就是提取…

5G学习笔记之Non-Public Network

目录 0. NPN系列 1. 概述 2. SNPN 2.1 SNPN概述 2.2 SNPN架构 2.3 SNPN部署 2.3.1 完全独立 2.3.2 共享PLMN基站 2.3.3 共享PLMN基站和PLMN频谱 3. PNI-NPN 3.1 PNI-NPN概述 3.2 PNI-NPN部署 3.2.1 UPF独立 3.2.2 完全共享 0. NPN系列 1. NPN概述 2. NPN R18 3. 【SNPN系列】S…

【专题】2024年悦己生活消费洞察报告汇总PDF洞察(附原数据表)

原文链接&#xff1a; https://tecdat.cn/?p38654 在当今时代背景下&#xff0c;社会发展日新月异&#xff0c;人们的生活方式与消费观念正经历深刻变革。MoonFox 月狐数据的《2024 年悦己生活消费洞察报告》聚焦于这一充满活力与变化的消费领域。随着就业、婚姻等社会压力的…

Latex+VsCode+Win10搭建

最近在写论文&#xff0c;overleaf的免费使用次数受限&#xff0c;因此需要使用本地的形式进行编译。 安装TEXLive 下载地址&#xff1a;https://mirror-hk.koddos.net/CTAN/systems/texlive/Images/ 下载完成直接点击iso进行安装操作。 安装LATEX Workshop插件 设置VsCode文…