Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  Other questions about Obi Cloth
#1
Pregunta 
Hi José!

First of all we wanted to thank you for your patience and prompt disposition to help us. Thanks to this, we have managed to solve most of the problems we had.

In this opportunity we write you, because we have 3 topics that we need your help to solve:



1) We are currently working with a Kinect sensor and have applied Obi Cloth to an avatar's dress. However, we often find that the dress "crosses" an ObiCollider from the character's leg (tunneling). In fact, we were able to replicate this in their demo scene:

[Image: 1_duda.jpg]

We know that solving the issue of tunneling is not simple. We have seen your video explaining this. However:

Is there a way to detect by code the event when a dress with ObiCloth passes through an ObiCollider on the leg?

In our case, we want to force a "reset" when the dress goes through an ObiCollider on the leg, but we don't know how to detect that event.



2) We followed your instructions to copy the information from one blueprint to another, and it worked well for us. We are doing the following:


Code:
// We assign the mesh to the blueprint
blueprintFinal.inputMesh = bakedMesh;

// We generate the blueprint
yield return blueprintFinal.Generate();

// We copy the particle groups:
        blueprintFinal.ClearParticleGroups();
        for (int i = 0; i < blueprintReferencia.groups.Count; ++i)
        {
            var group = blueprintFinal.AppendNewParticleGroup(blueprintReferencia.groups[i].name);
            for (int j = 0; j < blueprintReferencia.groups[i].particleIndices.Count; ++j)
            {
                group.particleIndices.Add(blueprintReference.groups[i].particleIndices[j]);
            }
        }

// We assign the blueprint created to the Obi Cloth
dressCloth.clothBlueprint = blueprintFinal

// We save the new blueprint in file
        AssetDatabase.CreateAsset(blueprintFinal, "Assets/CBP Dress 1 Final.asset");
        AssetDatabase.SaveAssets();



Although we managed to save the new Blueprint in a file, when trying to edit this new saved blueprint, it gives us this error:

[Image: 2_duda.jpg]

It seems that something needs to be done to save the blueprint file, and then edit it manually.

What do you think we need to do to edit the saved blueprint file?



3) For our project we have to create 4 blueprints at runtime, which are generated based on four "bakedMesh" that we generate, which are created from four base meshes with their respective blendshapes applied.

As we have to call the method "blueprint.Generate()" four times, the program tends to "stop" several times, while each of the methods "Generate()" is executed.

To improve the user experience and make the application look smooth, we would like to be able to create these 4 Blueprints using a Thread, for which we have done this:

[Image: 3_1_duda.jpg]


However, the system throws us this error:

[Image: 3_2_duda.jpg]


Analyzing more in detail the method "Generate()", we have realized that the method "g.MoveNext()", located in line 300 of the class "ObiActorBlueprint", is the one that causes the problem, however this is a closed method.

[Image: 3_3_duda.jpg]


Is there a way to perform this process in several small steps (or ideally in a Thread), so that the program does not have to stop several times while generating the 4 blueprints?


Again, we are very grateful for your help in this regard!

Best regards!

PD: Le enviamos por e-mail estas mismas consultas. Muchas gracias por su gentil ayuda!
Reply
#2
Hi! I'll answer here so that others can benefit from the info, if you don't mind Sonrisa

1) This is a very difficult problem, because using kinect you can't limit the user's motion speed in any way to keep tunneling under control. Also, there's no easy way to know when the cloth has passed trough the leg, as colliders only have a notion of "inside the collider" or "outside the collider". However this does not give you any info regarding which side of the collider is considered valid and which one is undesirable.

Things I'd try:

- Make sure Obi's CCD can do its work. For this, all character limbs need to report linear and angular velocity vectors back to Obi so that the movement of the colliders can be predicted during collision detection. The ObiKinematicVelocities component should do a fine job at this, improving tunneling prevention. Add it to all limb colliders.

- Reduce the physics timestep, as well as kinect's refresh ratio (if possible). Making sure the character moves less from one simulation step to the next will greatly reduce the chances of tunneling.

2) Try appending the new particle groups after saving the blueprint as an asset. Particle groups are sub-assets, so they will not be saved if there's no physical file to save them to yet.

3) First and more importantly: you can't call any Unity API methods from outside the main thread, except for a few ones such as Debug.Log(). This is a basic limitation of Unity, and the reason why you can't generally use multithreading unless you're very careful.

Generate() is a coroutine, as evidenced by its return type: IEnumerator. As such, its purpose is to "spread" work over multiple frames so that the main thread is not blocked for too long. You can even show a progress bar if needed, this is what it's done in editor to inform the user of the generation progress. However you can't call a coroutine that uses the Unity API from a thread other than the main thread. Coroutines are designed to allow for easy concurrency without parallelism, so no need to use threads if all you need is concurrency. If you're unfamiliar with coroutines, see: https://docs.unity3d.com/Manual/Coroutines.html

The IEnumerator.MoveNext() method is an internal C# method. It's used to move to the next enumerator element. In the case of coroutines, it advances the coroutine until the next yield instruction. Calling MoveNext() in a loop basically ensures the coroutine is completed before continuing execution. If any exception happens before reaching the next yield (in this case, the exception is caused by a call to a Unity API method from outside the main thread), it will be thrown by MoveNext(). See: https://docs.microsoft.com/es-es/dotnet/...etcore-3.1

So in short, use coroutines as they're intended to be used Guiño:

Code:
yield return StartCoroutine(blueprint.Generate());

If you capture the return value of the coroutine and advance it yourself instead of yielding, you can do:

Code:
IEnumerator coroutine = blueprint.Generate();
CoroutineJob.ProgressInfo progressInfo;

do{
    if (!coroutine.MoveNext())
        progressInfo = null;
    else
        progressInfo = coroutine.Current as CoroutineJob.ProgressInfo;
            
        // write your own method to update or show a progress bar: userReadableInfo contains info about what the coroutine is currently doing,
        // progress is a float ranging from 0 to 1 that represent the percentage of completion.
    ShowProgressBar(progressInfo.userReadableInfo, progressInfo.progress);
}while (progressInfo != null);

best regards!
Reply