Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Join us on March 30, 2023, between 5 am & 1 pm EST, in the Performance Profiling Dev Blitz Day 2023 - Q&A forum and Discord where you can connect with our teams behind the Memory and CPU Profilers.
    Dismiss Notice

Bug GameObjectConversionUtility.ConvertGameObjectHierarchy on same changed prefab disposes collider

Discussion in 'Physics for ECS' started by Jawsarn, Feb 12, 2020.

  1. Jawsarn

    Jawsarn

    Joined:
    Jan 12, 2017
    Posts:
    208
    Using GameObjectConversionUtility.ConvertGameObjectHierarchy on the same prefab twice, which in-between you change CollisionFilter, causes the PysicsComponent blobasset to become invalid on entity prefabs converted from the same gameObject prefab.
     
  2. Adam-Mechtley

    Adam-Mechtley

    Unity Technologies

    Joined:
    Feb 5, 2007
    Posts:
    290
    Hi! Can you please provide a very simple script demonstrating the issue? We'd need to see the use case to reason about what the behavior should be.

    That said, if this is blocking you, I would suggest you instead create a separate prefab variant for the alternate set of collision filters. (I'd also advise avoiding using GameObjectConversionUtility.ConvertGameObjectHierarchy() at run-time and instead do something like the object spawner sample script: https://github.com/Unity-Technologi...Common/Scripts/SpawnRandomObjectsAuthoring.cs)
     
  3. Jawsarn

    Jawsarn

    Joined:
    Jan 12, 2017
    Posts:
    208
    Some simple code. My use case is that I parent dynamic physics objects to simulate interior of moving entities, using layers, causing it to be in "parent space". (spaceships with interior) So all things that can be inside the spaceships will need these different layers as there are multiple ships. So sure I could work around by creating X amount of layers prefabs manually or by some editor script, but it's not a nice solution to do for 20-30 different interior things.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using Unity.Entities;
    4. using Unity.Physics.Authoring;
    5. using UnityEngine;
    6.  
    7. public class FilterSpawningDataAuthoring : MonoBehaviour, IConvertGameObjectToEntity
    8. {
    9.     public GameObject prefab;
    10.  
    11.     public void Convert(Entity entity, EntityManager dstManager, GameObjectConversionSystem conversionSystem)
    12.     {
    13.         var filter = prefab.GetComponent<PhysicsShapeAuthoring>();
    14.  
    15.         List<Entity> entities = new List<Entity>();
    16.  
    17.         // 10 for different layers
    18.         for (int i = 0; i < 10; i++)
    19.         {
    20.             filter.BelongsTo = new PhysicsCategoryTags()
    21.             {
    22.                 Value = (uint)(1 << i)
    23.             };
    24.             filter.CollidesWith = new PhysicsCategoryTags()
    25.             {
    26.                 Value = (uint)(1 << i)
    27.             };
    28.             entities.Add(GameObjectConversionUtility.ConvertGameObjectHierarchy(prefab, conversionSystem.ForkSettings((byte)(i + 1))));
    29.         }
    30.  
    31.         // Avoid dealloc on buffer
    32.         var buffer = dstManager.AddBuffer<FilterSpawningDataElement>(entity);
    33.         for (int i = 0; i < entities.Count; i++)
    34.         {
    35.             buffer.Add(new FilterSpawningDataElement() { filterPrefab = entities[i] });
    36.         }
    37.     }
    38. }
    39.  
    40. public struct FilterSpawningDataElement : IBufferElementData
    41. {
    42.     public Entity filterPrefab;
    43. }
    44.  
    45. public class SpawnSystem : ComponentSystem
    46. {
    47.     EntityQuery m_group;
    48.     protected override void OnCreate()
    49.     {
    50.         base.OnCreate();
    51.         m_group = GetEntityQuery(ComponentType.ReadOnly<FilterSpawningDataElement>());
    52.     }
    53.     protected override void OnUpdate()
    54.     {
    55.         Entities.With(m_group).ForEach((Entity entity) =>
    56.         {
    57.             var buffer = EntityManager.GetBuffer<FilterSpawningDataElement>(entity);
    58.  
    59.             for (int i = 0; i < buffer.Length; i++)
    60.             {
    61.                 PostUpdateCommands.Instantiate(buffer[i].filterPrefab);
    62.             }
    63.             PostUpdateCommands.RemoveComponent<FilterSpawningDataElement>(entity);
    64.         });
    65.     }
    66. }
    Also simple project
    https://drive.google.com/drive/u/0/folders/1bQKXYRL1UwMNtcNB6qe3YZ8C3jOQlwkG
     
    Last edited: Feb 18, 2020