社区问答 | 本周问答汇总 1026-1101

文摘   科技   2024-11-01 20:00   上海  

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

本期问题目录:

新手答疑:
1. ViewportToWorldPoint 为什么会返回 0,0 坐标?

2. 我的 Unity hub 无法进行登录,点击 sign in 没有反应

团结引擎:

3. Unity 团结引擎导出 harmonyOS 工程运行报错

4. 团结引擎 1.3.1 的空工程在鸿蒙 5.0 模拟器崩溃

5. 团结引擎的 meta 文件和 Unity 引擎的 meta 文件不兼容导致项目版本管理出现问题
微信小游戏:
6. 微信小游戏 UnityWebRequestAssetBundle 下载资源报错

技术支持:

7. Cloud Code c# 获取 ServiceToken

8. Addressables.LoadAssetAsync 加载不到最新 AB

9. 游戏第一次运行会卡顿

10. Unity 最新版 ECS 中,如何使用纯编程创建一个可以渲染的立方体?
新手答疑
  Q1.ViewportToWorldPoint 为什么会返回 0,0 坐标?
public class Viewport : Singleton<Viewport> { float minX, maxX, minY, maxY; void Start() {       Camera mainCamera = Camera.main;       Vector2 bottomLeft = mainCamera.ViewportToWorldPoint(new Vector3(0f, 0f));       Vector2 topRight = mainCamera.ViewportToWorldPoint(new Vector3(1f,1f));       minX = bottomLeft.x;       minY = bottomLeft.y;       maxX = topRight.x;       maxY = topRight.y;    }
//让player调用函数限制移动public Vector3 PlayerMoveablePoint(Vector3 playerPosition){ Vector3 position=Vector3.zero; position.x=Mathf.Clamp(playerPosition.x,minX,maxX); position.y = Mathf.Clamp(playerPosition.y, minY, maxY); return position; }}

MainCamera Z 轴设置为 -10,但返回的两个坐标均为 0 坐标,怎么办,求大神解答。  

自答:

如果摄像机 z 轴与目标距离为 10,可将 clipping planes near 参数调置 10 左右,再将这个参数带入 ViewportToWorldPoint 函数即可。

  Q2.我的 Unity hub 无法进行登录,点击 sign in 没有反应

自答:
最后是将 edge 浏览器设为默认浏览器搞定的。
团结引擎
  Q3.Unity 团结引擎导出 harmonyOS 工程运行报错
团结引擎 (1.3.1) 导出鸿蒙项目 (SDK 9),build fail
hvigor Finished :entry:default@BuildJS... after 348 ms
hvigor ERROR: Failed :entry:default@CompileArkTS...
hvigor ERROR: ENOENT: no such file or directory, stat 'D:\3D\tuanjie\HarmonyProject\entry\src\main\ets\workers\TuanjieMainWorkerHandler.ets.ts'
COMPILE RESULT:FAIL {ERROR:1}
hvigor ERROR: BUILD FAILED in 3 s 18 ms
Process finished with exit code -1

官方回答:

1.3.1 支持的是 API 12,SDK5.0。请使用对应的 SDK

  Q4.团结引擎 1.3.1 的空工程在鸿蒙 5.0 模拟器崩溃

团结引擎 1.3.1 版本创建的空工程只添加了两个 button,导出的鸿蒙工程在 DevEco-Studio 5.0.3906 的模拟器上启动崩溃。

答主 溜肉段:

目前应该是不支持模拟器,建议使用真机测试。

  Q5.团结引擎的 meta 文件和 Unity 引擎的 meta 文件不兼容导致项目版本管理出现问题
我把 Unity 项目导入到团结引擎之后,meta 文件因为不兼容的问题全部重新生成了一遍,但是我们项目还是用 Unity 开发,导致团结引擎重新生成的 meta 文件不能提交到 git 上面,这样的情况下如果在 git 上面提交了变更,再用团结引擎打开时还是要重新生成一遍,这种情况下大家都是怎么处理的?在 git 上面再创建一个分支给团结引擎项目使用么?

答主 溜肉段:

可以手动进行同步,并创建一个团结引擎的分支,建议不要频繁切换引擎哦~
微信小游戏
  Q6.微信小游戏 UnityWebRequestAssetBundle 下载资源报错
通过 UnityWebRequestAssetBundle 下载.ab文件,小游戏工具提示webgl.wasm.framework.unityweb.js:4564 Error while downloading Asset Bundle: Failed to decompress data for the AssetBundle ``` UnityWebRequest www = UnityWebRequestAssetBundle.GetAssetBundle(urlPath); Debug.LogFormat(" test urlPath" + urlPath); yield return www.Send(); if (www.isHttpError) { Debug.LogError(GetType() + "/ERROR/" + www.error); } else { AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(www); // ab.LoadAsset if (_info.action!=null) { _info.action(bundle); } } www.Dispose();
```

官方回答:

首先注意检查打包 AB 时设置的平台是微信小游戏,另外再看看 CDN 下载下来的文件,以及微信小游戏本身的资源缓存是不是之前版本的文件。

如果打包 AB 使用的是 SBP,请将 Scriptable Build pipeline 和 Addressable package 升级到最新版本。

技术支持
  Q7.Cloud Code c# 获取 ServiceToken

使用 Cloud Code C# 时,如何在 Java Web 项目中,获取 ServiceToken,用于调用 REST API 访问相应内容?

团结 MuseChat 已解答:

要在 Java Web 项目中获取 ServiceToken 并调用 REST API,可以按照以下步骤进行:
1. 在 C# 中获取 ServiceToken: 在 Cloud Code 模块中,可以通过 IExecutionContext 接口获取 ServiceToken。以下是一个示例代码,展示如何在 Cloud Code 模块中获取 ServiceToken 并将其返回:
using Microsoft.Extensions.Logging;using Unity.Services.CloudCode.Core;using Unity.Services.CloudCode.Shared;
namespace ExampleModule{ public class TokenModule { private static ILogger<TokenModule> _logger;
public TokenModule(ILogger<TokenModule> logger) { _logger = logger; }
[CloudCodeFunction("GetServiceToken")] public string GetServiceToken(IExecutionContext context) { try { return context.ServiceToken; } catch (Exception ex) { _logger.LogError("Failed to get service token. Error: {Error}", ex.Message); throw new Exception($"Failed to get service token. Error: {ex.Message}"); } } }}

2. 在 Java Web 项目中调用 Cloud Code API:使用上述 C# 代码获取到的 ServiceToken,可以在 Java Web 项目中调用 Cloud Code API。以下是一个 Java 示例代码,展示如何使用 ServiceToken 调用 Cloud Code API:

import java.io.IOException;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.Response;
public class CloudCodeClient { private static final String CLOUD_CODE_URL = "https://cloud-code.services.api.unity.com/v1/projects/<PROJECT_ID>/modules/<MODULE_NAME>/<FUNCTION_NAME>"; private static final String SERVICE_TOKEN = "<YOUR_SERVICE_TOKEN>";
public static void main(String[] args) { OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder() .url(CLOUD_CODE_URL) .addHeader("Authorization", "Bearer " + SERVICE_TOKEN) .build();
try (Response response = client.newCall(request).execute()) { if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
// Handle the response System.out.println(response.body().string()); } catch (IOException e) { e.printStackTrace(); } }}
3. 配置和运行:将 C# 代码部署到 Cloud Code 模块中。
  • 在 Java Web 项目中,替换为实际的值。
  • 运行 Java 代码,调用 Cloud Code API 并处理响应。
通过以上步骤,您可以在 Java Web 项目中获取 ServiceToken 并调用 REST API 访问相应内容。

  Q8. Addressables.LoadAssetAsync 加载不到最新 AB

Addressables.LoadAssetAsync 加载不到最新的 AB 资源。
AKey 与 BKey 是相同分组的资源,其中 AKey 是首包资源,BKey 是热更包内的新增资源; 首包 AB 为 BaseBundle,热更包 AB 为 HotFixBundle。
使用 LoadAssetAsync 加载 Akey,加载的是 BaseBundle(加载 BaseBundle 是错误的,因为 AKey 和 Bkey 分组到同一个 AB 包,所以当更新 BKey 资源打出 HotFixBundle 后,AKey 也会一同更新,最新依赖应该是 HotFixBundle,因此按理是要加载到热更 HotFixBundle的),而 Load BKey 返回 null。
相同加载策略下,CKey 资源属于首包 AB (CBaseBundle),但后面也有热更 AB (CHotFixBundle) 更新,使用 LoadAssetAsync 加载 CKey 则是能正常加载到这个热更 AB(CHotFixBundle) 的。
如果 AKey、BKey、CKey 都只会去查找首包资源还能理解,但是 Ckey 是正常的而AKey、BKey 有问题就很纳闷。
补充信息:通过 AKey、BKey、CKey 去打印相关的 dependencies 能够打印到正确的依赖:AKey 依赖 BaseBundle、HotFixBundle;
BKey 依赖 HotFixBundle;
CKey 依赖 CBaseBundle、CHotFixBundle;

自答:

已解决:出问题的 AB 包内都是 .asset 资源。经测验,热更的 .asset 在加载时都不会正常依赖到最新的 AB 包,还未去确认为什么。例子中的 CKey 为非 .asset 资源,因此加载是正常的。解决办法是通过挂载到预制上并热更预制,最后从预制上获取到最新的 .asset 资源。

  Q9. 游戏第一次运行会卡顿

我的游戏安装在手机,第一次运行时怪物出现会卡顿一下,重新场景第二次就不会了。请问这怎么解决?

答主 SKODE丨程序开发:

第一次的话,加载过慢很正常,如果不能接受可以提前做个预处理的模块。

  Q10. Unity 最新版 ECS 中,如何使用纯编程创建一个可以渲染的立方体?

网上和官方大量的教程基本都是通过 GameObject+Baker 烘培成 ECS 对象。那如果是针对一个纯代码生成动态场景的项目,就没有 GameObject 了,甚至预制体也没有,mesh、material 都是动态组合的,这个时候就完全没必要使用 baker 了。这个时候要怎么生成一个 entity 进行渲染呢?我看一些教程说是渲染的核心组件是 LocalTransform、RenderBounds、RenderMeshArray,我都添加上去了,但是没有渲染出来,这是为什么呀?是还缺什么其他必要的组件吗?在 Entity 层级面板中,是看到已经生成这个 entity 了,但是场景里不显示。

相关版本:

Unity6000.0.15f1c1

Entities 包 v1.2.4

Entities Graphics 包 v1.2.4

URP 项目

相关代码:

说明:组件已经确定挂载到场景里了,并且 mesh 和 material 两个属性都赋值了,并且是正确的模型和材质。

public class EcsCmpTest1 : MonoBehaviour {using Unity.Rendering;using Unity.Transforms;using UnityEngine;using Unity.Mathematics;using Unity.Entities;

public class EcsCmpTest1 : MonoBehaviour {
public Mesh mesh; public UnityEngine.Material material;
void Start() { fun(); Debug.Log("end .."); }

private void fun() { World world = World.DefaultGameObjectInjectionWorld;
EntityManager em = world.EntityManager; EntityArchetype archetype = em.CreateArchetype( typeof(LocalTransform) , typeof(LocalToWorld) , typeof(RenderBounds) , typeof(RenderMeshArray) );
Entity entity = em.CreateEntity(archetype); Debug.Log("entity.Index = " + entity.Index); em.SetComponentData<LocalTransform>(entity, new() { Position = new float3(0, 0, 0), Rotation = quaternion.identity, Scale = 1 }); em.SetComponentData<RenderBounds>(entity, new() { Value = this.mesh.bounds.ToAABB() }); em.SetSharedComponentManaged<RenderMeshArray>(entity, new( new UnityEngine.Material[] { this.material }, new Mesh[] { this.mesh } ));
}
}
自答:

自己解决了,Unity 封装了一个 RenderMeshUtility.AddComponents 工具方法,用这个方法可以自动补充 entity 渲染模型需要的组件。

public Mesh mesh;    public Mesh mesh2;    public UnityEngine.Material material;
// ...

核心代码在下面的最后一行。

EntityManager entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;    var entity = entityManager.CreateEntity();
// 添加Translation组件 entityManager.AddComponentData(entity, new LocalTransform { Position = transform.position, Rotation = quaternion.identity, Scale = 10 });
RenderMeshArray rm = new RenderMeshArray( new UnityEngine.Material[] { this.material }, new Mesh[] { this.mesh, this.mesh2 }, new MaterialMeshIndex[0] ); RenderMeshDescription meshDescription = new(); // 这里可以先用默认配置 meshDescription.FilterSettings = RenderFilterSettings.Default; // 暂时不使用光照探针 meshDescription.LightProbeUsage = UnityEngine.Rendering.LightProbeUsage.Off; // 这里的0、1表示RenderMeshArray中mesh或material数组里数据的索引 MaterialMeshInfo materialMeshInfo = MaterialMeshInfo.FromRenderMeshArrayIndices(0, 1);

RenderMeshUtility.AddComponents(entity, entityManager, meshDescription, rm, materialMeshInfo);


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

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



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