我的代码将对象设置为错误的父对象,如何修复此问题?

2024-06-30

因此,我目前正在为一篇学校论文进行编程,当前我的代码工作计划,或者至少我认为应该是,在使用碰撞作为拖放条件下,将对象设置为指定父级的子级。使用 if 条件的传感器。然而,当我运行游戏时,我小时候想要设置的对象被错误的父母使用。这基本上就是发生的情况。

因此,在层次结构中看到的网格下的图像是我想要由另一个父级指定为子级的图像。

层次结构中的字母 SLot 是我想在运行时指定为图像的父级的内容。

When I run the game, this is basically what happens: Image 3

正如您所看到的,在我看来,图像游戏对象以某种方式将自己指定为场景本身的子对象(如果我理解正确的话)。

这是我用于此逻辑的代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;

public class ParentSetter : MonoBehaviour
{
    public bool IsOnSlot = false;
    [SerializeField] GameObject[] LetterInputTile;
    
    [SerializeField] GameObject letterInputTileParent;
    // Start is called before the first frame update
    void Start()
    {
        letterInputTileParent = new GameObject("LetterInputTileParent");
        LetterInputTile = GameObject.FindGameObjectsWithTag("MLetterTile");
    }

    // Update is called once per frame
    void Update()
    {
        foreach (GameObject obj in LetterInputTile)
        {
            if (IsOnSlot)
            {
                for (int i = 0; i < LetterInputTile.Length; i++)
                {
                    LetterInputTile[i].transform.SetParent(letterInputTileParent.transform);
                }
            }
            else
            {
                for (int i = 0; i < LetterInputTile.Length; i++)
                {
                    LetterInputTile[i].transform.SetParent(null);
                }
            }
        }

    }

    private void OnCollisionEnter2D(Collision2D other)
    {
        if(other.gameObject.CompareTag("MLetterTile"))
        {
            IsOnSlot = true;
        }
    }

    private void OnCollisionExit2D(Collision2D other)
    {
        if (other.gameObject.CompareTag("MLetterTile"))
        {
            IsOnSlot = false;
        }
    }
}

IS my logic somehow wrong somewhere? or did I set something in the inspector wrong? Image of inspector: Image 4

它是检查器中的 Parent Setter 组件吗?

我该如何解决?

Update: The code seems to be working as intended according to the inspector as seen in the image. Image 5

但问题似乎仍然存在,层次结构似乎并不这么认为,并且仍然将自己指定为对象的父级。

我该如何解决?


你正在做

 LetterInputTile[i].transform.SetParent(null);

这会将您的对象设置为场景根级别。但他们似乎UI.Image必须嵌套在 a 下的组件Canvas以便被渲染。

还有你新创建的对象LetterInputTileParent不嵌套在Canvas但在场景根级别。

=> 你很可能更愿意维护

  • the LetterInputTileParent
  • 和瓷砖本身

总是嵌套在Canvas对于所有情况。

为此,您可以例如找到并做

// If possible it is always better to directly reference your objects via the Inspector
// In order to avoid any runtime issues and save some performance
[SerializeField] Canvas _canvas;

private void Awake()
{
    // As a fallback find the canvas on runtime - assuming there is only one anyway
    if(!_canvas) _canvas = FindObjectOfType<Canvas>();

    // You could/should also rather create this one beforehand 
    // and reference this directly via the Inpector
    if(!letterInputTileParent ) 
    {
        letterInputTileParent = new GameObject("LetterInputTileParent");
        // Make sure it is under the Canvas
        letterInputTileParent.AddComponent<RectTransform>();
        letterInputTileParent.SetParent(_canvas.transform, false);
    }

    LetterInputTile = GameObject.FindGameObjectsWithTag("MLetterTile");
}

一般来说,我不完全理解你的组件背后的逻辑。但你似乎把它附加到每个LetterSlot。然而你却发现all带有标签的对象MLetterTile。它们不是同时运行吗?

我也不会这样做Update和一个布尔标志一遍又一遍。

您已经有两个事件消息,所以为什么不处理那里的结果once.

另请注意你的循环foreach然后是嵌套的for循环是完全多余的并且迭代相同的项目

private void OnCollisionEnter2D(Collision2D other)
{
    if(other.gameObject.CompareTag("MLetterTile"))
    {
        foreach (GameObject obj in LetterInputTile)
        {
            obj.transform.SetParent(letterInputTileParent.transform);
        }
    }
}

private void OnCollisionExit2D(Collision2D other)
{
    if (other.gameObject.CompareTag("MLetterTile"))
    {
        foreach (GameObject obj in LetterInputTile)
        {
            obj.transform.SetParent(/*probably not null but something else see above*/);
        }
    }
}

很可能您甚至不想迭代at all- 考虑一下,您似乎要检查与数组中的对象完全相同的标签的碰撞=>您只想仅作为父对象this other您碰撞的对象,甚至可能不需要创建新的父对象。

我怀疑你更想要实现的是

  • 如果一个对象带有标签MLetterTile与槽碰撞
  • 将此插槽设置为对象的新父级
  • 如果它退出插槽
  • 将其设置回其原始父级

所以我宁愿期待类似的东西

public class ParentSetter : MonoBehaviour
{
    private readonly Dictionary<Transform, Transform> originalParents = new ();

    private void OnCollisionEnter2D(Collision2D other)
    {
        if(!other.gameObject.CompareTag("MLetterTile")) return;
        
        originalParents[other.transform] = other.transform.parent;

        other.transform.SetParent(transform);
    }

    private void OnCollisionExit2D(Collision2D other)
    {
        if(!other.gameObject.CompareTag("MLetterTile")) return;
        
        if(!originalParents.Remove(other.transform, out var originalParent)) return;

        other.transform.SetParent(originalParent);
    }
}

In the originalParents你现在同时发现

  • 当前位于此槽中的对象(originalParents.Keys)
  • 原始父母在退出插槽时重置它们
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我的代码将对象设置为错误的父对象,如何修复此问题? 的相关文章

  • 生成一定范围内的 N 个随机数,其总和为常数

    我想生成从 a b 之间的特定分布 例如均匀随机 抽取的 N 个随机数 其总和为常数 C 我尝试了一些我自己能想到的解决方案 以及在类似线程上提出的一些解决方案 但是他们中的大多数要么适用于有限形式的问题 要么我无法证明结果仍然遵循所需的分
  • 在 C# 中获取 Selenium RemoteWebDriver 的会话 ID

    我正在尝试获取在 SauceLabs 云上运行的测试的会话 ID 但我似乎无法访问它 我尝试过以下方法 Returns null var sessionId string RemoteWebDriver driver Capabilitie
  • C#:迭代数据表:Rows、Select() 或 AsEnumerable()

    foreach DataRow row in myDataTable Select foreach DataRow row in myDataTable AsEnumerable foreach DataRow row in myDataT
  • 使用脚本取消设置 PDF 字体

    我正在使用 xhtml2pdf 库自动创建 PDF 几个月前我有过这个问题 https stackoverflow com questions 25203219 xhtml2pdf doesnt embed helvetica 库嵌入了我没
  • C# 泛型方法,new() 构造函数约束中的类型参数

    有没有办法创建一个使用的通用方法new 要求类具有特定类型的构造函数属性的约束 例如 我有以下代码 public T MyGenericMethod
  • 配置 SourceTrail 以接受带有 @ 语法的嵌入式 c/c++ 头文件

    我正在尝试使用 Sourcetrail https www sourcetrail com https www sourcetrail com 快速了解 pic18 系列微控制器的一些旧嵌入式 c c 源代码 导入硬件包含文件时出现错误 该
  • 如何在 C# 中检查互联网连接是否可用

    我为一家公司开发了一个软件 出于某种许可目的 我使用远程数据库来允许 禁止使用该软件 每次用户登录软件时都会应用此任务 如果互联网连接不存在或对远程数据库的查询失败 用户会收到错误 他无法登录软件并显示远程数据库http地址 我不希望他看到
  • 如何在 c#.net 中将十进制转换为 ASCII?

    谁能帮助我如何使用 C net 将十进制转换为 ASCII 当我在文本框 1 中输入小数时 单击 转换 按钮后 结果将显示在文本框 2 中 我的问题是如何将十进制转换为 ASCII 的代码 这个怎么做 这是我在网上找到的一个简单的解决方案
  • 类内枚举前向声明是否可能? [复制]

    这个问题在这里已经有答案了 我知道在 C 11 中可以转发声明枚举类型 如果提供了存储类型 例如 enum E short void foo E e enum E short VALUE 1 VALUE 2 但我想转发声明一个类中定义的枚举
  • 如何使用OpenCV的归一化相关性?

    如何使用 OpenCV 的归一化相关性 有人可以提供代码示例吗 我的问题 我有一个螺丝头图像 需要找到螺丝的中心 所以我正在考虑使用 OpenCV 相关性 这是一个好主意吗 您可以在下面的链接下找到示例图像 http imageshack
  • 格式化具有 X 位小数和 InvariantCulture 的数字?

    我想使用格式化数字ToString CultureInfo InvariantCulture 并且精确到小数点后 5 位 这可以使用ToString N5 我怎样才能同时做这两件事 怎么样使用重载既需要格式又需要文化 http msdn m
  • 在 C# 中创建新 List 的这三种方式有什么区别?

    这三种创建新的方式有什么区别List
  • 从包含 n 个元素的向量中随机选择 m 个元素

    我有一个向量包含n元素 我需要选择一个子集m向量中随机出现的元素 不重复 做到这一点最有效的方法是什么 我需要在我的代码中执行此操作数千次 我想到的解决方案是使用rand 生成一个随机数k之间0 and n 然后选择k向量中的第一个元素并将
  • cmake:如何在只有 target_link_directories (没有 target_link_libraries)的共享库中设置 rpath?

    我的项目的目标如下 从我的主可执行文件中 我想加载一个库 libfoo so 加载第二个库 libbar so 我不想在任何路径中指定相对或绝对路径filename我传递给的参数dlopen 即我希望我的代码读取 dlopen libfoo
  • 当找到路由/url 但未找到其背后的资源时返回什么?

    当路由customer 1存在但customer搜索背后的资源 实体不存在时 我应该返回 404 吗 我的意思是路线存在 或者我应该返回一个 204 无内容 因为我找不到客户 结果为空 微软样本 public IHttpActionResu
  • Microsoft.Graph GetAsync() 无限期挂起

    介绍 我正在开发一个 ASP NET 应用程序 除其他外 它应该从 Azure Active Directory 检索用户 为此 我使用 Microsoft Graph 版本 1 14 0 预览库 可以找到该库here https www
  • 单元测试依赖注入

    我在用Autofac for IoC 这是我的容器启动器类 其职责是注册依赖项 public class ContainerInit public static IContainer BuildContainer var conFac ne
  • Asp.net MVC 2 缓存

    我目前正在使用 c 中的 asp net mvc 2 开发一个网站 我从未使用过 MVC 中的缓存功能 并且想将其应用到用户个人资料页面 此页面上的内容很少更改 唯一需要实时的部分是用户最近发布的帖子列表 我使用linq to sql从数据
  • Dapper 中的自定义映射

    我正在尝试使用带有 Dapper 和多重映射的 CTE 来获取分页结果 我遇到了重复列的不便 例如 CTE 阻止我命名列 我想将以下查询映射到以下对象 而不是列名和属性之间的不匹配 Query WITH TempSites AS SELEC
  • C# 替换 Byte[] 中的字节

    替换字节数组中的某些字节的最佳方法是什么 例如我有bytesFromServer listener Receive ref groupEP 我可以做BitConverter ToString bytesFromServer 将其转换为可读格

随机推荐