社区问答 | 本周问答汇总 0525-0607

文摘   科技   2024-06-07 18:48   上海  

本文汇总了 2024 年 5 月 25 日 - 2024 年 6 月 7 日 Unity 中文社区精选问答。如果在使用 Unity 过程中遇到任何问题,欢迎点击阅读原文前往 Unity 中文社区提问,将有官方技术支持及社区贡献者当日解答此外,本周还有少量待解决问题,欢迎小伙伴们到社区分享经验,为他人答疑解惑。

本期问题目录:

新手答疑:
1. 我希望我的角色的武器可以根据检测到敌人的方位而改变方向
2. Unity 绑定按键的问题
3. UnityWebGL 无法输入中文
4. 使用 SceneManager.LoadScene 多场景切换,切换场景显示组件被销毁
5. InputField 有些输入不进去
6. 请问如何在导出 exe 能够自适应显示的比例
7. 如何将三维场景读取为 C# 的二维矩阵?

8. 无法实现在屏幕二上的射线检测

Unity 引擎:
9. Unity 开播放模式,动画,时间轴,掉帧
新手答疑
  Q1.我希望我的角色的武器可以根据检测到敌人的方位而改变方向

我有一个角色,他有一个附加在角色上的武器,我希望这个我的角色可以检测附近并且锁定敌人,并使我的武器朝向改变。在我攻击时,我希望我的武器可以按照当时的角度增加或者减少角度。

答主 团结 MuseChat

为实现您描述的功能,您可以通过编写脚本来控制角色的武器朝向,并使其锁定敌人。以下是一个简单的示例代码,演示了如何实现这一功能:
首先,您需要一个脚本来控制武器的朝向和锁定敌人。您可以将以下代码添加到您的武器脚本中:
using UnityEngine;
public class WeaponController : MonoBehaviour{ public Transform target; // 敌人的Transform public float rotationSpeed = 5f; // 武器旋转速度
void Update() { if (target != null) { // 获取敌人方向 Vector3 targetDirection = target.position - transform.position; targetDirection.y = 0f; // 确保武器在水平方向上旋转
// 旋转武器朝向敌人 Quaternion targetRotation = Quaternion.LookRotation(targetDirection); transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime); } }}

在这段代码中,我们首先获取敌人的方向,然后使用 Quaternion.LookRotation 来计算武器应该朝向的旋转角度,并通过 Quaternion.Slerp 来平滑地旋转武器朝向敌人。

接下来,您可以在角色控制器脚本中检测敌人并更新武器的目标。以下是一个简单的示例代码:

using UnityEngine;
public class CharacterController : MonoBehaviour{ public WeaponController weaponController; // 武器控制器
void Update() { // 检测敌人,这里假设敌人是以Tag为"Enemy"的对象 GameObject enemy = GameObject.FindGameObjectWithTag("Enemy");
if (enemy != null) { // 更新武器的目标为敌人的Transform weaponController.target = enemy.transform; } }}
在这段代码中,我们在角色控制器中检测敌人,并将敌人的 Transform 传递给武器控制器的 target 属性,从而实现武器朝向敌人的功能。
请根据您的具体需求和游戏逻辑进行适当的调整和扩展。希望这可以帮助您实现角色武器根据检测到敌人的方位而改变方向的功能!
  Q2.Unity 绑定按键的问题

我想设置人物攻击,通过按键 j 来改变 trigger,可是 Unity 中识别不到。

团结 MuseChat 已解决:
要在 Unity 中绑定按键以触发人物攻击动作,您可以按照以下步骤进行设置:
在 Unity 中设置输入:首先,您需要在 Unity 的输入管理器中设置按键 J 对应的输入。您可以按照以下步骤进行设置:
1. 依次点击 Unity 编辑器菜单中的 “Edit” > “Project Settings” > “Input”。
2. 在 Input Manager 中,找到您要设置的按键(例如 Fire1),将 Positive Button 设置为 J 键。
编写脚本:创建一个脚本来检测按键 J 的输入并触发人物攻击动作。以下是一个示例脚本,您可以根据您的需求进行调整:
using UnityEngine;
public class AttackController : MonoBehaviour{ private Animator animator;
void Start() { animator = GetComponent<Animator>(); }
void Update() { if (Input.GetKeyDown(KeyCode.J)) { // 触发攻击动作,这里假设使用Trigger来控制攻击动作 animator.SetTrigger("Attack"); } }}

将脚本附加到人物角色:将上述编写的脚本(例如 AttackController.cs)附加到您的人物角色对象上。

设置 Animator Controller:确保您的人物角色的 Animator Controller 中包含了名为 "Attack" 的Trigger 参数,并且有对应的攻击动画状态。

通过以上步骤,您可以在 Unity 中绑定按键 J 来触发人物的攻击动作。

  Q3.UnityWebGL 无法输入中文

在 Unity 打包 webgl 后,InputFiled 组件里无法输入中文,我在网上看到说用 InputMark_WebGL 这个插件,但我用了之后打包就会报错,想问问大佬们有遇到过吗

Unity 版本 2019.4.38;平台 webgl

错误日志
答主 ManHua:
用这个插件试试,你可以把这个插件里面的高级语法改成 C# 7.0 的。

https://github.com/kou-yeung/WebGLInput

  Q4.使用 SceneManager.LoadScene 多场景切换,切换场景显示组件被销毁

需求:实现场景切换显示对应页面。之前是基于场景 A 实现,全部现在想把场景 A 的弹窗那些弄到场景 B 内,这样两边切换实现。 
遇到问题:场景 A 切换到场景 B,再切换回去时,显示场景 A 需要用的组件信息被销毁。使用 DontDestroyOnLoad 还是有问题就页面东西太多了,然后重复加载不销毁的组件。希望大佬能讲解一下到底应该怎么使用场景切换。

答主 Mark

创建一个 UI 控制器,专门控制 UI 的显示与隐藏。通过场景控制器则监听 SceneManager.sceneLoaded 判断场景加载状态并通知 UI 控制器显示对应的 UI。

  Q5. InputField 有些输入不进去

我在每一个空都添加了 InputField,为什么输入的时候有些输入不进去,有些能输入进去。

答主 年少有你、Mark

查看一下是否出现 UI 遮挡的情况,示例如下:
还可以写代码测试当前点击的 UI 是什么。我之前也是遇到类似问题,用这个代码检查出来了,你可以试试:
/// <summary>    /// 获得当前点击到的UI物体    /// </summary>    public void Skode_GetCurrentSelect()    {        // if (Input.GetMouseButtonDown(0))        // {        //     GameObject obj = null;        //        //     GraphicRaycaster[] graphicRaycasters = FindObjectsOfType<GraphicRaycaster>();        //        //     PointerEventData eventData = new PointerEventData(EventSystem.current);        //     eventData.pressPosition = Input.mousePosition;        //     eventData.position = Input.mousePosition;        //     List<RaycastResult> list = new List<RaycastResult>();        //        //     foreach (var item in graphicRaycasters)        //     {        //         item.Raycast(eventData, list);        //         if (list.Count > 0)        //         {        //             // for (int i = 0; i < list.Count; i++)        //             // {        //             //     obj = list[i].gameObject;        //             // }        //             obj = list[0].gameObject;        //         }        //     }        //        //     if (obj)        //     {        //         Debug.LogError(obj.name);        //     }        // }    }

  Q6.请问如何在导出 exe 能够自适应显示的比例

我在编辑的时候 game 窗口设置的是 4K,但是导出 exe 的时候由于显示器的分辨率不是 4K,会出现错位的情况,请问如何在导出 exe 能够自适应显示的比例。

答主 君莫笑:

官方文档:https://docs.unity3d.com/cn/2019.3/Manual/HOWTO-UIMultiResolution.html 
在 Unity 中实现自适应布局以适配不同分辨率设备可以通过以下几种方法来实现:
1. Canvas Scaler:使用 Canvas Scaler 组件可以实现 UI 元素的自适应缩放。Canvas Scaler 提供了三种模式:Constant Pixel Size(固定像素大小)、Scale with Screen Size(随屏幕大小缩放)、Constant Physical Size(固定物理大小),您可以根据需求选择合适的模式来适配不同分辨率设备。
2. Anchors:在设计 UI 时,使用 Anchors 来确定 UI 元素的位置和大小。通过设置 Anchors,可以确保 UI 元素在不同分辨率下保持相对位置和比例。
3. Aspect Ratio:在设计 UI 时,考虑设备的宽高比,尽量设计可以适应不同宽高比的界面布局。
4. Viewport:使用 Camera 的 Viewport Rect 属性来控制相机视图在屏幕上的位置和大小,以确保在不同分辨率下显示正确。
5. 代码适配:根据不同分辨率设备动态调整 UI 元素的位置和大小。可以编写脚本来根据当前设备分辨率计算 UI 元素的位置和大小,从而实现自适应布局。
通过以上方法结合使用,您可以实现在 Unity 中实现自适应布局,以适配不同分辨率设备,并提供更好的用户体验。
  Q7.如何将三维场景读取为 C# 的二维矩阵?
是一个项目上的问题,主要是关于 Unity 的,问题可以简单描述如下:现在有一个 Unity 三维场景,主要由如下几部分构成:
  • 海岸(图中黑色)
  • 三维的船(图中深蓝)
  • 岛屿(图中棕色)
  • 波动的海洋(图中浅蓝)

面的图是二维的,而实际上的场景是三维的,类似下面这样

目前主要的问题是:

在 Unity 中,需要通过什么方式,可以“读取”这个场景,同时将其转换为一个 C# 中的二维矩阵?
其中矩阵索引代表坐标,该位置的值为 0 表示此处是海岸,值为 1 表示此处为船,值为 2 表示此处为岛屿,值为 3 表示此处为海面
场景是实时变化的,需要“读取”得到的二维矩阵也是实时变化的?

答主 ManHua:

主要思路是通过获取特定标签的物体,然后将其位置映射到二维矩阵中,并根据物体标签设置相应的矩阵值。
using UnityEngine;
public class SceneToMatrix : MonoBehaviour{ public int matrixWidth = 10; // 矩阵宽度 public int matrixHeight = 10; // 矩阵高度
private int[,] objectMatrix; // 二维数组,用于表示场景中对象所占据的位置
void Update() { // 初始化二维数组 objectMatrix = new int[matrixWidth, matrixHeight];
// 获取场景中的所有对象 GameObject[] objects = GameObject.FindGameObjectsWithTag("SceneObject");
foreach (GameObject obj in objects) { Vector3 position = obj.transform.position;
int x = Mathf.FloorToInt(position.x) + matrixWidth / 2; int y = Mathf.FloorToInt(position.z) + matrixHeight / 2;
// 新增边界检查 if (x < 0 || x >= matrixWidth || y < 0 || y >= matrixHeight) { continue; // 跳过超出范围的物体 }
// 检查坐标是否超出矩阵范围 if (x >= 0 && x < matrixWidth && y >= 0 && y < matrixHeight) { // 根据对象的标识符设置矩阵中的值 if (obj.CompareTag("Coast")) { objectMatrix[x, y] = 0; } else if (obj.CompareTag("Ship")) { objectMatrix[x, y] = 1; } else if (obj.CompareTag("Island")) { objectMatrix[x, y] = 2; } else if (obj.CompareTag("Ocean")) { objectMatrix[x, y] = 3; } } }

}}
  Q8.无法实现在屏幕二上的射线检测

无法实现在屏幕二上的射线检测,在编辑模式或者只有一个屏幕可以进行射线检测,当导出 Exe 文件后,Input.mousePosition 无法在屏幕二上点击在镜头发出射线进行射线检测。

代码如下:
ca = GetComponent<Camera>(); Vector3 mousePoint = Input.mousePosition; Ray ray = ca.ScreenPointToRay(mousePoint); RaycastHit raycastHit; 
if (Physics.Raycast(ray, out raycastHit,100, layerMask)) {}
Unity 2020.3.34;PC

自答:

已经解决了,导出后 PC 端后,多个屏幕的情况下需要处理鼠标在屏幕的位置,直接使用 RelativeMouseAt(查询相对鼠标坐标)函数转换即可,就可以导出后在屏幕二进行射线检测着 

Vector3 mousePoint = Display.RelativeMouseAt(Input.mousePosition); Ray ray = ca.ScreenPointToRay(mousePoint);

Unity 引擎

  Q9.Unity 开播放模式,动画,时间轴,掉帧
我的 Unity 播放模式下会掉帧,在非播放模式下,播放时间轴和动画轴也掉帧,但是只要不在播放模式和不动动画轴和时间轴的情况下就一直很正常,我一直找不到问题所在,重启和新建项目都有这个问题,Unity 和启动器分别卸载又下回来还有这个问题怎么办求大神们解决一下
Unity 版本是 2019.4.22
答主 Mark:

可能是版本 BUG 导致的,建议使用 LTS 版本试试是否还存在这种问题。

本系列问题汇总将每周更新,欢迎点击阅读原文,与 Unity 中文社区成员一起答疑互助,共同进步。
长按关注
Unity 官方开发者服务平台
第一时间了解 Unity 社区动向,学习开发技巧

 点击“阅读原文”,访问 Unity 社区问答



Unity官方开发者服务平台
Unity引擎官方开发者服务平台,分享技术干货、学习课程、产品信息、前沿案例、活动资讯、直播信息等内容。
 最新文章