How to Spawn and grab new atoms from script ?

JFKxxx

New member
Messages
10
Reactions
2
Points
3
Hi everyone.
So I finally resolved to get into plugin creation.

I'm a new VAM user and also a c# beginner and not a pro coder at all but I have managed to make a first simple shitty plugin for personnal use, and now I want to dig deeper (I have a few c++ skills so I'm not a total newbie).

I'm sure there is a lot of things I still need to learn so I'll try t break it into small questions, and hopefully get one of the local gurus to mentor me ;)

Right now I'm trying to wrap my head around atom spawning and manipulation from scripts. I'm trying to play with the SuperController.singleton.AddAtomByType() instruction.
To put it short, here's what bothers me :

C#:
 private void Callback()
        {
          SuperController.singleton.AddAtomByType("CustomUnityAsset"); 
          // won't compile, because the call is ambiguous                
        }
private void Callback()
        {            
            SuperController.singleton.AddAtomByType("CustomUnityAsset","MyUID");
            //will compile, but the atom doesn't spawn
        }
private void Callback()
        {            
            SuperController.singleton.AddAtomByType("CustomUnityAsset","MyUID", false, false, false); 
            //will compile, but the CUA doesn't spawn        
        }
private void Callback()
        {            
            SuperController.singleton.AddAtomByType("CustomUnityAsset", false, false, false);
            // CUA Spawns with default UID        
        }

I also struggle to "grab" the aotm once spawned.

for example :

C#:
private void Callback()
{

    Atom myAtom=new Atom(); 
    SuperController.singleton.AddAtomByType("Person", false, false, false);
    myAtom = SuperController.singleton.GetAtomByUid("Person");
    
    SuperController.LogMessage(myAtom.toString());
}  // will work, "Person" atome spawns and is stored in the Atom object

private void Callback()
{

    Atom myAtom=new Atom(); 
    SuperController.singleton.AddAtomByType("CustomUnityAsset", false, false, false);
    myAtom = SuperController.singleton.GetAtomByUid("CustomUnityAsset");
    
    SuperController.LogMessage(myAtom.toString());
}  // spawns CUA but not stored in myAtom

Basically I'm trying to find a reliable way to spawn an atom and "grab" it in memory to customise it, I can't understand why the GetAtomByUid function grabs the person but not the CUA
(I've tried with GetAtomById() too with the same results), and I Feel I'm missing a correct reliable way to create an atom, manipulate it in memory BEFORE instanciate it, whithout the need to use some tricky string search based function to "grab" the atom afterwards.

Something like:

C#:
Atom myAtom=new Atom();

myAtom = CreateAtomFunction(type, UID, etc.);
//..do things with myAtom
myAtom.Instanciate();

Right now, I'd like to spawn an CUA with a particular UID, but as I can't neither specify it on spawn, nor grab it when it spawns with the default name, I can't do anything with it.
For reason I can't understand, I can do it with a person, but not a CUA... What am I missing ?

Any good soul to help me through this ? ^^

PS: I'm not a native english speaker so I hope I'm clear enough, especially when it comes to tech things...
Thanx in advance for answering !
 
C#:
//will compile, but the CUA doesn't spawn
SuperController.singleton.AddAtomByType("CustomUnityAsset","MyUID", false, false, false);

// CUA Spawns with default UID
SuperController.singleton.AddAtomByType("CustomUnityAsset", false, false, false);
The first method is a Coroutine, you see that because it returns an IEnumerator. Coroutines are a Unity engine thing that utilizes yield instructions, which again is a C# feature. Basically the engine will keep calling your method again every frame. Imagine a for-loop through the IEnumerator object, where you do one iteration every frame. Its worth nothing that coroutines are NOT multi-threading. They are frequently used to wait for something to load without blocking the main thread, in this case waiting for the Atom to spawn. While the actual loading happens in another thread, the check whether that loading finished can be done in the coroutine. You can also wrap Coroutines in other Coroutines, something we gonna use below.
More info: https://docs.unity3d.com/2018.1/Documentation/Manual/Coroutines.html

In VaM and it's AddAtomByType method some atom types actually use the coroutine while others spawn instantly. That's why it works with the Person atom.

So you could do it like this:
C#:
using UnityEngine;
using UnityEngine.Events;
using System;
using System.Collections;
using System.Collections.Generic;
   
public class TestPlugin : MVRScript
{
    private Atom myAtom;
    private bool myAtomWasLogged = false;
   
    public override void Init()
    {
        SetupButton("Spawn", OnSpawnButton, false);
    }
   
    private void OnSpawnButton()
    {
        IEnumerator createCoroutine = CreateCustomUnityAssetCo("MyNewCUA");
        StartCoroutine(createCoroutine);
    }
   
    private IEnumerator CreateCustomUnityAssetCo(string aUID)  
    {
        myAtom = null;
        myAtomWasLogged = false;
        SuperController sc = SuperController.singleton;
       
        // VaM might rename our Atom if it already exists, like adding #2 to the name.
        // To be able to find our new atom, we give it a random unique UID and then rename it later.
        // If you are SURE your new ID doesn't exist yet, e.g. because you checked already, you don't need this inefficient nonsense.
        string tempUID = GetUniqueTempUID();      
       
        yield return sc.AddAtomByType("CustomUnityAsset", tempUID, false, false, false);          
        myAtom = sc.GetAtomByUid(tempUID);
       
        sc.RenameAtom(myAtom, aUID);
       
       
        // ======================================
        // You could customize your new atom here
        // ======================================
    }
   
    private string GetUniqueTempUID()
    {
        List<string> uids = SuperController.singleton.GetAtomUIDs();
        string uid;
        do
        {
            uid = Guid.NewGuid().ToString();
        } while (uids.Contains(uid));
        return uid;
    }
   
    private void Update()
    {
        if (myAtom != null && !myAtomWasLogged)
        {
            SuperController.LogMessage("Atom spawned! " + myAtom.uid);
            myAtomWasLogged = true;
           
           
            // ============================================
            // Or....you could customize your new atom here
            // ============================================
        }
    }
   
    private void SetupButton(string label, UnityAction callback, bool rightSide)
    {
        UIDynamicButton button = CreateButton(label, rightSide);
        button.button.onClick.AddListener(callback);
    }
}
 
Thanks a lot for this explanation. I thought it had something to do with Coroutines. I'll look into that.

Thank you very much !

(BTW : thanks for your amazing logickbricks plugin, and especially yout MAcGruber_utils.cs library, it saved me a LOT of digging !)
 
Last edited:
Back
Top Bottom