Below is a small list of tips and tricks for scene and plugin creation that I've learned while working with VAM and creating plugins. Many of these are probably already well known to old experienced users, but some may not have heard of them, so I'm sharing it here. — Tricks - CUA with the Standard Unity shader in Fade or Transparent render mode can be hidden using the built-in VAM UIImage atom - set it Background Alpha = 0.004 (strict), Image Alpha = 0, both Colors = 0-0-0 and RenderQueue = 2999 (strict) - as a result, when you look at such CUA through this UIImage, it will be "cut off" (hidden) exactly in those places where they visually intersect. - If you have VAM Glass atom onto which Directional Light shines, turn off Glass "Pixel Light" checkbox to prevent it from flickering. - To prevent the arms/legs from passing through the Person body when abruptly rewinding the Timeline to the beginning, switch the animation to frame 0, then go to the "Pose Tab" and click "Use Current Pose". It's important to uncheck "Include Morphs" before, otherwise data from Naturalis or other plugins that modify morphs will be retained. The idea is that the animation will "jump" to this pose when resetting without taking physics into account, which will completely eliminate (or at least significantly reduce) collision and clothing issues. - If Light (especially Directional) passes through headwear/clothing and does not cast a shadow and/or illuminates objects it should not reach, use VAMTweaks and set Shadow Cascads = 4. - If when you move Main camera on Y axis there is an effect that the Skybox also moves, it needs to be scaled via PhysicsObject -> Scale (usually by 5-10 times). - You can use BlurCube atom with Pexilization = 0.0001 (strict) and RenderQueue = 3000 to create X-Ray effect on any clothing which is visually located behind it (while its scaling and rotation along the axes will be taken into account). — For plugins developers - Get ALL components of the specified type (FindObjectsOfType works unreliably and often does not return even active atoms) Button[] AllButtons = Resources.FindObjectsOfTypeAll(typeof(Button)) as Button[]; - Remove current plugin manager.RemovePluginWithUID(storeId.Substring(0, storeId.IndexOf("_"))); - Get the current plugin index (works with any numbers) int CurrentPluginIndex = int.Parse(storeId.Substring(7, storeId.IndexOf("_") - 7)) - Create a UVTemplate of some clothing itme and get it as a Texture2D (with subsequent deletion of temporary file) public override void Init () { DAZSkinWrap[] dressedСlothe = containingAtom.GetComponentsInChildren(); MaterialOptions neededVAMMaterial = dressedСlothe[#NeededClothIndex].gameObject.GetComponents()[#NeededMaterialIndex] as MaterialOptions; string customTextureFolderBackup = neededVAMMaterial.customTextureFolder; neededVAMMaterial.customTextureFolder = "Custom"; neededVAMMaterial.CreateUVTemplateTexture(); neededVAMMaterial.customTextureFolder = customTextureFolderBackup; StartLoadingTexture("Custom\\" + (neededVAMMaterial.storeId.Substring(neededVAMMaterial.storeId.IndexOf(":") + 1) + "UVTemplate.png")); } public void StartLoadingTexture (string texturePath) { ImageLoaderThreaded.QueuedImage queuedImage = new ImageLoaderThreaded.QueuedImage(); queuedImage.imgPath = texturePath; queuedImage.forceReload = false; queuedImage.createMipMaps = false; queuedImage.isNormalMap = false; queuedImage.isThumbnail = false; queuedImage.linear = true; queuedImage.createAlphaFromGrayscale = false; queuedImage.compress = false; queuedImage.callback = new ImageLoaderThreaded.ImageLoaderCallback(ApplyLoadedTexture); ImageLoaderThreaded.singleton.QueueImage(queuedImage); } public void ApplyLoadedTexture (ImageLoaderThreaded.QueuedImage queuedImage) { SomeTexture2DVariable = queuedImage.tex; FileManagerSecure.DeleteFile(queuedImage.imgPath); } - Public (available) Timeline functions public const string Animation = "Animation"; public const string Segment = "Segment"; public const string NextAnimation = "Next Animation"; public const string PreviousAnimation = "Previous Animation"; public const string NextAnimationInMainLayer = "Next Animation (Main Layer)"; public const string PreviousAnimationInMainLayer = "Previous Animation (Main Layer)"; public const string NextSegment = "Next Segment"; public const string PreviousSegment = "Previous Segment"; public const string Scrubber = "Scrubber"; public const string Time = "Set Time"; public const string Play = "Play"; public const string PlayIfNotPlaying = "Play If Not Playing"; public const string IsPlaying = "Is Playing"; public const string Stop = "Stop"; public const string StopIfPlaying = "Stop If Playing"; public const string StopAndReset = "Stop And Reset"; public const string NextFrame = "Next Frame"; public const string PreviousFrame = "Previous Frame"; public const string Speed = "Speed"; public const string Weight = "Weight"; public const string Locked = "Locked"; public const string Paused = "Paused"; - Paths where the plugin can create files (those with "true" do not require user manual confirmation) FileManager.RegisterPluginSecureWritePath("Saves", false); FileManager.RegisterPluginSecureWritePath("Custom", false); FileManager.RegisterPluginSecureWritePath("Saves/PluginData", true); FileManager.RegisterPluginSecureWritePath("Custom/PluginData", true); - setCallbackFunction is not called if Set is equal to the current value - Open the current plugin UI (only works if it was opened manually at least once before) manager.pluginListPanel.GetChild(int.Parse(storeId.Substring(7, storeId.IndexOf("_") - 7))).GetChild(7).GetChild(0).GetChild(1).GetComponent