I am experimenting with embedding IronPython in a Unity 3D project and I've run into some errors I can't seem to figure out.
I have the following script attached to a GameObject in Unity.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using IronPython;
using IronPython.Modules;
using System.Text;
public class IronPythonWrapper : MonoBehaviour {
void Start() {
ScriptTest();
}
public static void ScriptTest() {
// create the engine
var engine = IronPython.Hosting.Python.CreateEngine();
// and the scope (i.e. the Python namespace)
var scope = engine.CreateScope();
// execute the Python script
engine.ExecuteFile("Assets/Scripts/ipscript.py");
// grab the variable from the Python scope
string commands = scope.GetVariable<string>("commands");
Debug.Log(commands);
}
}
The goal is to have the IronPython engine instantiated above execute the following simple Python script, called ipscript.py.
commands = "Script executed."
When I enter play mode (in Unity) I get the following error.
MissingMemberException: 'ScopeStorage' object has no attribute 'commands'
Does anyone have any idea what I should investigate to resolve this problem? Perhaps I need to implement some error trapping so I can see any exceptions IronPython is generating when it executes the Python script?
Your python execution is not properly passing the scope. Your commands variable is therefore created on a transient scope that is discarded after executing the python file and the explicitly created scope has no idea what commands is.
The snippet should read like
engine.ExecuteFile("Assets/Scripts/ipscript.py", scope);
Related
I just started game development and got into a problem
whenever I load my Visual Studio code into Unity it says
The refrenced script unknown on this behaviour is missing
This is my script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class VirtualManMovement : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
Debug.Log("Hello, World!") ;
}
// Update is called once per frame
void Update()
{
}
}
I need a solution for this
This may happen is the file name does not match the class name. Make sure that the file containing this script is also named VirtualManMovement.cs
Make sure in Unity you go to edit -> preferences and see that you have Unity External tools in Your IDE Selected.
Ensure your Code File Name is the same as your Class to prevent confusion.
I was confused as well when I first started. Hopefully, you find this useful
I have an SSIS data flow that contains a script Component as a source. I'd like to generate the source data by running a script on an SQL Server database. The connection string to be used to connect to the database is set to be sensitive. How can I read this sensitive parameter inside the script component using C#?
In a Script Task, usually it is read for example as the following:
string mySecretPassword = Dts.Variables["$Project::MySecretPassword"].GetSensitiveValue().ToString
The Variable class in a Script Task has a GetSensitiveValue method. However, the Script Component Variable implements the interface Microsoft.SqlServer.Dts.Runtime.Wrapper.Variable which has no GetSensitiveValue method defined.
Let's assume the connection string is a project parameter for now.
Despite the lack of a GetSensitiveValue method existing in the Script Component, I was able to access the value just fine.
What I did fumble with was my Package Protection level and how it interacts with Project Parameters that are marked as Sensitive.
I defined a Project Parameter named MySecretPassword and populated it with SO_71308161 and marked it as sensitive.
Script Source
I defined a single column output and my intention was to just push the password into the dataflow to confirm I was able to access it
using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
public string MySecret;
public override void PreExecute()
{
base.PreExecute();
MySecret = Variables.MySecretPassword;
}
public override void CreateNewOutputRows()
{
Output0Buffer.AddRow();
Output0Buffer.Column = this.MySecret;
}
}
I then routed the data to a derived column and dropped a data viewer between the two. My code did not throw an exception but it did show an empty string.
If I tried to access my sensitive parameter value in a script task using myVariable.Value it would throw an error as expected but I was getting my sensitive value back.
Package Protection Level
I love StackOverflow questions that teach me things. My default mode is to define projects that use a Project & Package protection level of DontSaveSensitive. Which is incompatible with using Sensitive project parameters. Not incompatible in that it will throw an exception, but when you run the package, accessing that value will be blanked out (for strings at least).
As soon as I change the Project and then Package's protection level to EncryptSensitiveWithUserKey (or anything that isn't DontSaveSensitive), both the Script Task's .GetSensitiveValue() and the Script Component's Variables.MySecretPassword worked.
I am completely new to Unity and all other answers I've found for this go over my head.
So far I've run everything from the same script, which is getting very big and messy. Therefore I am trying to learn how to call methods from other scripts.
I have a dropdown menu with the code in one script and I'm trying to call that code from another.
ScriptA:
using UnityEngine;
public class ChoseLanguage: MonoBehaviour
{
public TMPro.TMP_Dropdown myDrop;
DisplayController displayController;
public void DropdownChooseLanguage()
{
if (myDrop.value == 1)
PlayerPrefs.SetString("chosenLanguage", "Spanish");
if (myDrop.value == 2)
PlayerPrefs.SetString("chosenLanguage", "Japanese");
if (myDrop.value == 3)
PlayerPrefs.SetString("chosenLanguage", "Korean");
if (myDrop.value == 4)
PlayerPrefs.SetString("chosenLanguage", "Icelandic");
Debug.Log(PlayerPrefs.GetString("chosenLanguage"));
displayController.DropdownSetLanguage();
}
}
The selection code works by itself, and the debug.Log shows that the chosen language is being saved correctly to PlayerPrefs.
The error comes when it tries to read the "displayController.DropdownChooseLanguage();" line. (Line 28)
Unity gives this error:
NullReferenceException: Object reference not set to an instance of an object
ChoseLanguage.DropdownChooseLanguage () (at Assets/Scripts/ChoseLanguage.cs:28)
Script B
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using System.Linq;
using TMPro;
public class DisplayController : MonoBehaviour
{
...
public void DropdownSetLanguage()
{
SetFileName();
setLanguage.gameObject.SetActive(false);
Start();
}
...
}
Earlier, the exact same code from Script A was placed in ScriptB and all the code worked as it should.
This is a very noob question but I have simply just never been able to understand how exactly to access other scripts correctly.
Any help will be greatly appreciated.
Thanks.
EDIT:
I found a solution to this but I'll keep the question up in case other beginners have the same problem or if anyone has a better solution.
I made the DisplayController displayController; into public DisplayController displayController; and then dragged the gameobject with the displaycontroller script attached into the slot for it.
DropdownSetLanguage is public and it seems you think you can access it by
creating a DisplayController object named displayController.
It is ok
about to access a class but, displayController should be null in this state.
Because you have to assign an initial DisplayController to displayController
in your first code.
You can add public or [Serializable] tag in front of
DisplayController displayController; in your first code then, you can add
a GameObject which has a DisplayController script in it in Unity editor.
accessibility
ERROR:
Object reference not set to an instance of an object.
I'm trying to create a DLL that can get the Entrypoint application name that is written in Powershell.
The layout is very simple:
In Powershell I add the line
Add-Type -Path ('C:\Users\Public\PS\DLL\get_value.dll')
then I create the object
$value = New-Object PS_get_value.Stack
and call the C# method
$rtn = $value.Get_stack()
If the Get_stack() method returns a basic string like "Test" it works fine….
BUT if I try to use the .net Assembly.GetEntryAssembly().Location (which should return the full path to the calling (parent) app), I get the error above.
I am trying to get the full path (or at least the filename) of the application script that is running in Powershell. I plan on using that value to validate that the program (PS script) is the one that should be running. If there is a different way for the C# code to get it that's fine. BTW if I run a normal program it works. I do know that there is something about managed code base, I'm not sure what that is.
Thanks for any help or direction your can give.
Code Example:
PS:
Add-Type -Path ('C:\Users\Public\PS\DLL\get_value.dll')
$addNum = New-Object PS_get_value.Stack
$_rtnKey = $addNum.Get_stack()
Write-Host "RTNed Key Version 2: $_rtnKey"
C# (the DLL):
using System;
using System.IO;
using System.Diagnostics;
using System.Reflection;
namespace PS_get_value
{
public class Stack{
public string Get_stack()
{
string _test_a = g_stack();
return _test_a;
}
public string g_stack()
{
return System.Reflection.Assembly.GetEntryAssembly().Location;
}
}
}
Give it a try by returning one of the following:
Assembly.GetExecutingAssembly().Location
or
Assembly.GetExecutingAssembly().CodeBase
This question already has answers here:
How to set up unit tests in Unity and fix missing assembly reference error?
(3 answers)
Closed 3 years ago.
I am trying to write unit tests in C# for the scripts that need to run inside Unity3D, later. My C# scripts are in the folder "Assets/Scripts" of the Unity project.
I am using Unity version 2019.1.0f2 with Visual Studio Community for Mac V8.0.5 (build 9), under Mac OS X version 10.14.4.
Unity has a test runner window that I used: Window > General > Test runner. Inside that test runner window, I clicked on "Play mode" and on "Create Playmode Test Assembly Folder". Unity created a folder called "Tests" for me in which I am supposed to put my tests. So far, so good.
Now here is the problem:
My test code cannot see the classes under test that are in the parent folder of that test folder!
This is the folder hierarchy:
Assets
Scripts
MyFirstScript.cs
Tests
MyTestScript.cs
Tests.asmdef
When I double-click on MyTestScript.cs, Visual Studio opens the solution and the source file OK. Now, I am trying to write
var x = new MyFirstScript();
and the compiler complains "The type or namespace name 'MyFirstScript' could not be found".
It seems as if the classes in the Scripts folder are completely unknown inside the classes that are in the Tests folder.
This is MyFirstScript.cs:
using UnityEngine;
public class MyFirstScript : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
And this is MyTestScript.cs:
using System.Collections;
using System.Collections.Generic;
using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools;
namespace Tests
{
public class MyTestScript
{
// A Test behaves as an ordinary method
[Test]
public void MyTestScriptSimplePasses()
{
var x = new MyFirstScript(); // problem occurs HERE!
// Use the Assert class to test conditions
}
// A UnityTest behaves like a coroutine in Play Mode. In Edit Mode you can use
// `yield return null;` to skip a frame.
[UnityTest]
public IEnumerator MyTestScriptWithEnumeratorPasses()
{
// Use the Assert class to test conditions.
// Use yield to skip a frame.
yield return null;
}
}
}
I expected that I could use the class MyFirstScript in my test code (MyTestScript). What can I do?
Check out the MonoBehaviourTest section of this manual page.
Note that with Unity, it's almost never a good idea to call 'new' on a MonoBehaviour-derived object. You almost always want to instantiate it by calling AddComponent() on a GameObject.