photo

[SOLVED] Issue accessing properties between C# components

Recommended Posts

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.

Share this post


Link to post

Hello,

myCamera is Unigine component 
public class myCamera : Component

it's mean, you couldn't create instance by using new operator
myCamera camera = new myCamera();

attach component to any node instead. For example add this line at myActor.Init()
camera = node.AddComponent<myCamera>();

Share this post


Link to post
Posted (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 by mind.matter

Share this post


Link to post

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

Share this post


Link to post
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)

Share this post


Link to post

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

Share this post


Link to post
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)

spacer.png

test.zip

Share this post


Link to post

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

Share this post


Link to post
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)

Share this post


Link to post