mind.matter Posted June 24, 2020 Share Posted June 24, 2020 Currently having issues accessing properties defined in one C# component from another, can someone help explain why camera.myPersecutor always returns null in myActor.cs rather than the object/node which was successfully assigned using the Unigine Editor? myActor.cs using System; using System.Collections; using System.Collections.Generic; using Unigine; [Component(PropertyGuid = "2bebe0d16765a3fcff8aaf2b9377fa8eff394095")] public class myActor : Component { public Node myTarget = null; myCamera camera = new myCamera(); private void Init() { // write here code to be called on component initialization if (myTarget) camera.myPersecutor.Target = myTarget; // How to access "Target" from generic "Player" class? else camera.myPersecutor.Target = node; // How to access "Target" from generic "Player" class? } private void Update() { // write here code to be called before updating each render frame } } myCamera.cs using System; using System.Collections; using System.Collections.Generic; using Unigine; [Component(PropertyGuid = "57924e2e9c813fb5e70e4d903e2043afdb211d42")] public class myCamera : Component { public Player myPersecutor = null; public Player mySpectator = null; private void Init() { // write here code to be called on component initialization } private void Update() { // write here code to be called before updating each render frame if (Input.IsKeyPressed(Input.KEY.DIGIT_1)) Game.Player = myPersecutor; if (Input.IsKeyPressed(Input.KEY.DIGIT_2)) Game.Player = mySpectator; Log.Error("\nCurrent Camera: {0} ({1})\n", Game.Player.Name, Game.Player.Type); } } Many thanks in advance. Link to comment
merzgling Posted June 25, 2020 Share Posted June 25, 2020 Hello, myCamera is Unigine component public class myCamera : Component it's mean, you couldn't create instance by using new operatormyCamera camera = new myCamera(); attach component to any node instead. For example add this line at myActor.Init() camera = node.AddComponent<myCamera>(); Link to comment
mind.matter Posted June 26, 2020 Author Share Posted June 26, 2020 (edited) On 6/25/2020 at 6:30 AM, merzgling said: attach component to any node instead. For example add this line at myActor.Init() camera = node.AddComponent<myCamera>(); @merzgling Thanks for the explanation, unfortunately this solution is not ideal if you need to abstract the "Camera" set-up from multiple "Actors". For example an application where users switch between 5 vehicles (myActor.cs * 5) using cameras stored in a separate parent node (myCamera.cs * 1) What would be the best/correct solution in this situation? Edited June 27, 2020 by mind.matter Link to comment
alexander Posted June 26, 2020 Share Posted June 26, 2020 Hi, Why camera.myPersecutor always returns null in myActor.cs rather than the object/node which was successfully assigned using the Unigine Editor? It's the correct behaviour. 1) You create an instance of "myActor" with the private member "camera" inside. This member is not null, but has null myPersecutor and mySpectator members (camera = new myCamera()). 2) Then the void Init() is executed. At this moment camera.myPersecutor is still null (nothing has changed between myActor's constructor and Init()). Do you have an instance of "myCamera" in the Unigine Editor? If so, change the line myCamera camera = new myCamera(); to public myCamera camera; and assign it in the Unigine Editor. How to access "Target" from generic "Player" class? Instead of this: camera.myPersecutor.Target = myTarget; use casting: (camera.myPersecutor as PlayerPersecutor).Target = myTarget; Best regards, Alexander Link to comment
mind.matter Posted June 27, 2020 Author Share Posted June 27, 2020 22 hours ago, alexander said: 2) Then the void Init() is executed. At this moment camera.myPersecutor is still null (nothing has changed between myActor's constructor and Init()). @alexander Thanks for the detailed explanation, this behaviour is now clearer. 22 hours ago, alexander said: Do you have an instance of "myCamera" in the Unigine Editor? If so, change the line @alexander Yes, myCamera.cs is assigned to a NodeDummy within the Editor, multiple Player... nodes also exist within NodeDummy. Unfortunately using public myCamera camera within myActor.cs results in the camera member itself returning null, previously only select fields/properties returned null. Perhaps this is a bug? (Unigine 2.11.0.2, Linux) Link to comment
alexander Posted June 30, 2020 Share Posted June 30, 2020 Hi mind.matter, Unfortunately using public myCamera camera within myActor.cs results in the camera member itself returning null, previously only select fields/properties returned null. Can you provide a small sample with this problem? Have you linked myCamera instance with the myActor? I tried to reproduce it but it looks fine. Best regards, Alexander sample_data.zip Link to comment
mind.matter Posted July 1, 2020 Author Share Posted July 1, 2020 On 6/30/2020 at 10:05 AM, alexander said: Can you provide a small sample with this problem? @alexander Please find a simple "Sample" project below, which fails to execute when using myActor.cs (camera returns null) test.zip Link to comment
alexander Posted July 2, 2020 Share Posted July 2, 2020 Oh, I see. You wrote [HideInEditor] public myCamera camera and expect that the member will be automatically assigned to any available node with a myCamera instance. It doesn't work that way. You need to use the singleton pattern. In your case rewrite myActor and myCamera as follows:myCamera.cs: using System; using System.Collections; using System.Collections.Generic; using Unigine; [Component(PropertyGuid = "da29aba3adda9ca677290bcdcb3d3ac8b17e9f87")] public class myCamera : Component { public static myCamera Instance; public Player myPersecutor = null; public Player mySpectator = null; // register the instance before executing other // components by using "Order" attribute [Method(Order = -1000)] private void Init() { Instance = this; } private void Update() { // write here code to be called before updating each render frame if (Input.IsKeyPressed(Input.KEY.DIGIT_1)) Game.Player = myPersecutor; if (Input.IsKeyPressed(Input.KEY.DIGIT_2)) Game.Player = mySpectator; Log.Error("\nCurrent Camera: {0} ({1})\n", Game.Player.Name, Game.Player.Type); } } myActor.cs: using System; using System.Collections; using System.Collections.Generic; using Unigine; [Component(PropertyGuid = "6f391b685068c7a7909ca0dab1c3fa71ce34b11c")] public class myActor : Component { public Node myTarget = null; private void Init() { if (myTarget) (myCamera.Instance.myPersecutor as PlayerPersecutor).Target = myTarget; else (myCamera.Instance.myPersecutor as PlayerPersecutor).Target = node; } } Best regards, Alexander Link to comment
mind.matter Posted July 3, 2020 Author Share Posted July 3, 2020 On 7/2/2020 at 5:49 AM, alexander said: It doesn't work that way. You need to use the singleton pattern. @alexander Thanks for the confirmation and example, our code/application now works as expected. This issue can be considered resolved (unable to edit title) Link to comment
Recommended Posts