How to see the Auto Reference section on Plugin Inspector? - unity3d

In the latest Unity manual
https://docs.unity3d.com/2019.1/Documentation/Manual/PluginInspector.html
they assert that the Plugin Inspector
now features an "Auto Reference" concept:
So using the latest Unity (and even trying .2 etc),
However no matter what I do I cannot make this appear. Every single Unity project I have tried, even Unity examples, does not have the feature.
How it looks for me ..
What is going on?
how to access the Auto Reference ?

tl;dr- "Auto reference" only works for managed plugins. that is a .dll file that was written in, and compiled from C#. Unmanaged plugins (dll's written in a language that is not C#, are unmanaged and can't be auto referenced)
edit: I just noticed there were more hidden comments, one of which was Aybe mentioning it working for managed DLL's.
edit2: if you want the project to test it out i can upload it.
I wanted to check if there was a difference between managed and unmanaged DLL's when inspecting in the editor (testing in Unity 2019, but I assume the same goes for 2018).
I made the following two DLL's. One in C# (managed) and one in CPP (unmanaged). I added some simply functionality to it to make sure it wouldn't be caused by having an empty dll.
Managed C# plugin
using System;
namespace TestDLLManaged
{
public class TestDLLManaged
{
public static float Multiply(int a, float b)
{
return a * b;
}
}
}
Compiled it into a DLL targeting .Net 3.5 framework (unity 2018 and later versions support 4.x, but wanted to play it on the safe side) and placed the .dll file in the /Assets/ folder (Apparantly the Assets/Plugin folder is intended to be used with native/unmanaged plugins, and not managed).
Unmanaged/native C++ plugin
//header filer
#pragma once
#define TESTDLLMULTIPLY_API __declspec(dllexport)
extern "C"
{
TESTDLLMULTIPLY_API float MultiplyNumbers(int a, float b);
}
//body
#include "TestDLLMultiply.h"
extern "C"
{
float MultiplyNumbers(int a, float b)
{
return a * b;
}
}
Also compiled this into a dll, and placed it in the /Assets/Plugin folder.
I call both DLL's inside DLLImportTest.cs and perform a simple calculation to make sure both DLL's are actually imported, and functioning like so
using static TestDLLManaged.TestDLLManaged;
public class DLLImportTest : MonoBehaviour
{
const float pi = 3.1415926535f;
[DllImport("TestDLL", EntryPoint = "MultiplyNumbers")]
public static extern float UnmanagedMultiply(int a, float b);
// Use this for initialization
void Start()
{
UnityEngine.Debug.LogFormat("validating unmanaged, expeceted result = 100: {0}", UnmanagedMultiply(10, 10f));
UnityEngine.Debug.LogFormat("validating managed, expeceted result = 100: {0}", Multiply(10, 10f));
}
}
When inspecting the DLL's in the editor it seems that the Managed (C#) plugin does have the option to auto reference and the Unmanaged/native (cpp) dll indeed doens't have the functionality. Now I don't actually know why this is the case, as it is nowhere to be found in the documentation. Maybe it's a bug, maybe there is another reason behind it. I may make a forum post about it later asking for more clarification.
As a little extra I decided to run a benchmark the two function, and to my surprise found that the managed C# plugin was actually faster than the cpp one.
private void BenchMark()
{
Stopwatch watch1 = new Stopwatch();
watch1.Start();
for (int i = 0; i < 10000000; i++)
{
UnmanagedMultiply(1574, pi);
}
watch1.Stop();
UnityEngine.Debug.LogFormat("Unmanaged multiply took {0} milliseconds", watch1.Elapsed);
Stopwatch watch2 = new Stopwatch();
watch2.Start();
for (int i = 0; i < 10000000; i++)
{
Multiply(1574, pi);
}
watch2.Stop();
UnityEngine.Debug.LogFormat("Managed multiply took {0} milliseconds", watch2.Elapsed);
}
Results:
Unmanaged multiply took 00:00:00.1078501 milliseconds
Managed multiply took 00:00:00.0848208 milliseconds
For anyone wishing to view the differences/experiment with it themselves, i've made a git-hub repo here containing the project i used above.

This question has been nicely resolved by #remy_rm
Compiled c# dlls ("managed plugins") do have the auto-reference feature
Actual native plugins ("unmanaged plugins") do NOT have the auto-reference feature
In fact this does apply identically on both PC and Mac:
Unity (sometimes) refers to:
c# compiled as a dll as "managed plugins"; and they (sometimes) refer to
native plugins (say, an actual static library for iPhone which is compiled C) as "unmanaged plugins".
(Whereas, all other Unity-related writing on the www generally refers to compiled c# as "dlls" and native plugins as "plugins".)
The auto-reference system is only for compiled c# .. "managed plugins".
A huge thanks to #remy_rm for spending hours resolving this issue.
Unity are trying and trying to improve their comic documentation - not quite there yet :)

Related

UPROPOERTY variables not showing in details

I´ve been trying to show some variables that I created in a C++ class and then create a Blueprint class based on it. But when I see the details of the object or try to find this variables in the Blueprints they do not show up.
I´ve basically copy and paste code from UE4 documentation see here: https://docs.unrealengine.com/en-us/Programming/Introduction, but the variables are not showing up for me.
// MyActor.cpp
#include "MyActor.h"
// Sets default values
AMyActor::AMyActor()
{
//PrimaryActorTick.bCanEverTick = true;
TotalDamage = 200.0f;
}
// Called when the game starts or when spawned
void AMyActor::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AMyActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// MyActor.h
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"
UCLASS()
class MYPROJECT3_API AMyActor : public AActor
{
GENERATED_BODY()
public:
UPROPERTY(EditAnywhere)
float TotalDamage;
// Sets default values for this actor's properties
AMyActor();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
};
I want to modify this variables from the Event Graph. Please help me find what I did wrong, if you need anymore information I will gladly provide it to you.
Use BlueprintReadWrite or BlueprintReadOnly
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float TotalDamage;
This just happened to me and feels like this is what might have happened to Juan Esteban as well, if you think your code is correct (and in my case it was):
"Hot Reloading" of the project was "stuck" in Unreal (i.e. changes made to the project didn't reflect in the editor), despite rebuilding the project and running "Refresh Visual Studio Project" from the file menu.
So... restarting Unreal actually fixed it.

Assigning multiple assets to multiple variables on inspector

Is there a way to assign multiple assets to multiple variables on the inspector???
My case is this, I have 5 objects, those objects have a script wich have around 1200 variables used to play SFXs. When Unity compile the script I have to manually drag and drop the SFX from the assets to the variable on the inspector, or go to the inspector, scrol to the variable, click the dot and then select the SFX file from the window.
Is there a way to speed this up?
You should create a public List of Audio Sources which will appear in inspector. Lock the inspector by clicking look in right top.
Now select all the files from Project and drag on list. All files will be added to list. Now if you want a specific file you can find the file by its name for example:
AudioSource GetAudioSource(string SourceName)
{
return audioSourceList.Find(item => item.Name == SourceName);
}
Use the Resources.LoadAll method to access all the assets from the path parameter via scripting. Probably put that method call in Start. Might have to rename the files to pull the right order from the LoadAll method if they result in some alternate order.
EDIT: Here's some example code...
(NOTE: Loads from Resources/Sound/SFX folder)
For reference: http://docs.unity3d.com/ScriptReference/Resources.LoadAll.html
public class YourClassNameGoesHere : MonoBehaviour
{
Public AudioClip[] BA;
void Start ()
{
BA = (AudioClip[]) Resources.LoadAll("Sound/SFX");
}
}
I found a solution for this problem. I must say, it's not perfect, in fact, it should not be used unless is absolutely necessary.
To speed up the assign you could do this:
Create a variable
public AudioClip ma, me, mi, mo, mu;
At Start() add
ma = Resources.Load("Sound/SFX/MA") as AudioClip;
me = Resources.Load("Sound/SFX/ME") as AudioClip;
mi = Resources.Load("Sound/SFX/MI") as AudioClip;
mo = Resources.Load("Sound/SFX/MO") as AudioClip;
mu = Resources.Load("Sound/SFX/MU") as AudioClip;
After compile the public variables will be available on the Inspector as empty variables, but, on runtime the variables will be filled with the content of the folder Resources/Sound/SFX (Assets\Resources\Sound\SFX).
Why shouldn't be use unless necessary?, first, it's a bad practice; second, it's a cheap trick that comes at a price (on mobile devices it load all the resources so will consume RAM fast). In my test, all my sound clips take as much as 169 MB. On PC it's not much of a problem, but if your target is Mobile games, this is something to take into consideration. And third, on web player, ALL resources will be streamed first.
On a side note, this cheap trick ignores the way Unity handles assets. Unity force you to assign assets manually because if the asset is not use, it will not be integrated into the build. This trick force everything to be loaded and be integrated into the final build, used or no. On the other hand, if you are assign it, you will use it... right?
The answer and example given by #Jayson Ash lead me to the right direction.

Why is my CE app refusing to run?

I've been maintaining a Windows CE app for some time now (over a year) and have produced new versions of it from time to time, copying them to the handheld device[s] and running the new versions there.
Today, though, I created a new Windows CE app for the first time. It is a very simple utility.
To create it in VS 2008, I selected a C# "Smart Device Project" template, added a few controls and a bit of code, and built it.
Here are some of the options I selected:
I copied the .exe produced via building the project to the handheld device's Program Files folder:
...but it won't run. Is it in the wrong location? Does it need some ancillary files copied over? Is there some other sort of setup I need to do to get it to run? Or what?
UPDATE
Since there's not much of it, I'm pasting ALL the code below in case somebody thinks my code could be the problem:
using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
namespace PrinterCommanderCE
{
public partial class PrinterCommanderForm : Form
{
public PrinterCommanderForm()
{
InitializeComponent();
}
private void btnSendCommands_Click(object sender, EventArgs e)
{
SendPrinterCommands();
}
private void SendPrinterCommands()
{
bool successfulSend = false;
const string quote = "\"";
string keepPrinterOn = string.Format("! U1 setvar {0}power.dtr_power_off{0} {0}off{0}", quote);
string shutPrinterOff = string.Format("! U1 setvar {0}power.dtr_power_off{0} {0}on{0}", quote);
string advanceToBlackBar = string.Format("! U1 setvar {0}media.sense_mode{0} {0}bar{0}", quote);
string advanceToGap = string.Format("! U1 setvar {0}media.sense_mode{0} {0}gap{0}", quote);
if (radbtnBar.Checked)
{
successfulSend = SendCommandToPrinter(advanceToBlackBar);
}
else if (radbtnGap.Checked)
{
successfulSend = SendCommandToPrinter(advanceToGap);
}
if (successfulSend)
{
MessageBox.Show("label type command successfully sent");
}
else
{
MessageBox.Show("label type command NOT successfully sent");
}
if (ckbxPreventShutoff.Checked)
{
successfulSend = SendCommandToPrinter(keepPrinterOn);
}
else
{
successfulSend = SendCommandToPrinter(shutPrinterOff);
}
if (successfulSend)
{
MessageBox.Show("print shutoff command successfully sent");
}
else
{
MessageBox.Show("print shutoff command NOT successfully sent");
}
}
private bool SendCommandToPrinter(string cmd)
{
bool success = false;
try
{
SerialPort serialPort = new SerialPort();
serialPort.BaudRate = 19200;
serialPort.Handshake = Handshake.XOnXOff;
serialPort.Open();
serialPort.Write(cmd);
serialPort.Close();
success = true;
}
catch
{
success = false;
}
return success;
}
}
}
UPDATE 2
Based on this, I added a global exception handler to the app so that Program.cs is now:
namespace PrinterCommanderCE
{
static class Program
{
[MTAThread]
static void Main()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(GlobalExceptionHandler);
Application.Run(new PrinterCommanderForm());
}
static void GlobalExceptionHandler(object sender, UnhandledExceptionEventArgs args)
{
Exception e = (Exception)args.ExceptionObject;
MessageBox.Show(string.Format("GlobalExceptionHandler caught : {0}", e.Message));
}
}
}
Yet running the new build shows nothing - it just "flashes" momentarily with about as much verbosity as Lee Harvey Oswald after Jack Ruby's friendly visit.
UPDATE 3
Could the problem be related to this, and if so, how to solve it?
The circumstance that both my updated version of an existing app AND this brand new and simple app refuse to run indicate there is something fundamentally flawed somewhere in the coding, building, or deployment process.
UPDATE 4
As this is a minimal utility, the reason it (and my legacy, much more involved) app are not working may have something to do with the project properties, how it's being built, a needed file not being copied over, or...???
NOTE: The desktop icon is "generic" (looks like a blank white form); this perhaps indicates a problem, but is it indicative of something awry or is it a minor (aesthetics-only) problem?
UPDATE 5
In Project > Properties..., Platform is set to "Active (Any CPU)" and Platform target the same ("Active (Any CPU)")
I have read that this is wrong, that it should be "x86", but there is no "x86" option available - Any CPU is the only one...?!?
UPDATE 6
In Project > Properties... > Devices, the "Deploy the latest version of the .NET Compact Framework (including Service Packs)" is checked. Is this as it should be?
UPDATE 7
Okay, here's the really strange part of all this:
I have two CF/CE apps that I need to run on these Motorola/Symbol 3090 and 3190 handheld devices.
One is this simple utility discussed above. I find that it actually does run on one of the devices (the 3190, FWIW). So it runs on one device, but not on the other.
HOWEVER, the other (legacy) .exe is the opposite - it runs on the 3090 (where the utility will not even start up), but not on the 3190.
So the utility's needs are met by the 3190, and the legacy util's needs are met by the 3090. However, the NEW version of the legacy app does not run on either device!
I am baffled; I feel as Casey Stengel must have when speaking once of his three catchers: "I got one that can throw but can't catch, one that can catch but can't throw, and one who can hit but can't do either."
UPDATE 8
The 3190 has a newer version of the CF installed; it seems that both the new and the old apps should run on the new device with the newer CE, but they don't - only the one built against/for the new framework does...
UPDATE 9
Here is what the 3090 looks like:
UPDATE 10
So I have two exes, one that runs on the devices (both of them now), and the other that will run on neither of the devices. The two exesw seem almost identical. I compared them with three tools: Red Gates' .NET Reflector; JetBrains' dotPeek, and Dependency Walker.
Here is what I found:
Dependency Walker
Both seem to have the same errors about missing dependencies (I didn't have them in the same folder with their dependent assemblies is probably the problem there)
.NET Reflector
The nonworking file has this entry that the working file does not:
[assembly: Debuggable(0x107)]
Is this the problem and, if so, how can I change it?
JetBrains dotPeek
The References in the working copy of the exe are all version 1.0.50000.0
The non-working exe has an identical list of References, and the same version number.
There is this difference, though:
For the working .exe, dotPeek says, "1.4.0.15, msil, Pocket PC v3.5"
For the non-working .exe, dotPeek says, "1.4.0.15, msil, .Net Framework v4.5"
Is this the problem and, if so, how can I change the non-working .exe to match the working one?
This last is disconcerting, primarily because I see no place in the non-working (newer) version of the project where a "4.5" string exists. Where could dotPeek be getting that information?
UPDATE 11
I do know now that the problem is somewhere between these two MessageBox.Show()s, because the first one I see, but not the second:
public static int Main(string [] args)
{
try
{
// A home-brewed exception handler (named ExceptionHandler()) is already defined, but I'm adding a global one
// for UNHANDLED exceptions (ExceptionHandler() is explicitly called throughout the code in catch blocks).
MessageBox.Show("made it into Main method"); // TODO: Remove after testing <= this one is seen
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(GlobalExceptionHandler);
string name = Assembly.GetExecutingAssembly().GetName().Name;
IntPtr mutexHandle = CreateMutex(IntPtr.Zero, true, name);
long error = GetLastError();
if (error == ERROR_ALREADY_EXISTS)
{
ReleaseMutex(mutexHandle);
IntPtr hWnd = FindWindow("#NETCF_AGL_BASE_",null);
if ((int) hWnd > 0)
{
SetForegroundWindow(hWnd);
}
return 0;
}
ReleaseMutex(mutexHandle);
DeviceInfo devIn = DeviceInfo.GetInstance();
Wifi.DisableWifi();
// Instantiate a new instance of Form1.
frmCentral f1 = new frmCentral();
f1.Height = devIn.GetScreenHeight();
f1.Text = DPRU.GetFormTitle("DPRU HHS", "", "");
MessageBox.Show("made it before Application.Run() in Main method"); // TODO: Remove after testing <= this one is NOT seen
Application.Run(f1);
devIn.Close();
Application.Exit();
return 0;
}
catch(Exception ex)
{
DPRU.ExceptionHandler(ex, "Main");
return 0;
}
} // Main() method
UPDATE 12
More specifically, I've got infinite looping going on somehow; By mashing the "Ent" pill on the handheld device (that's what the button looks like - a "lozenge") - it sounds like gerbils tap-dancing (as debugging MessageBox.Show()s in two methods pop up and are dismissed over and over ad infinitum ad (literally) nauseum).
If an application does not start it is mostly missing something. As you compiled for WindowsCE and CF3.5, the Compact Framework 3.5 runimes have to be installed on the WindowsCE device.
Normally Compact Framework is part of Windows CE images, at least version 1.0, but who knows for your test device? If at least one CF is installed, an app requiring a newer CF version will show that on start by a message stating about the missed version. So either no CF is on your device, or something is goind real wrong.
You can run \Windows\cgacutil.exe to check the CF version installed on the device. The tool will show the version of installed CF.
You can debug using a TCP/IP connection or ActiveSync connection. See remote debuggung elsewhere in stackoverflow, I wrote a long aanswer about remote debug via TCP/IP. Or does your device neither have USB and WLAN or ENET?
Update: Here is the answer for remote debug via tcp/ip: VS2008 remotely connect to Win Mobile 6.1 Device This will also enable the remote deployment "In Project > Properties... > Devices, the "Deploy the latest version of the .NET Compact Framework (including Service Packs)" is checked. Is this as it should be?"
Are the earlier apps you wrote also written .NET? Compact framework does not care about the processor architecture, only the CF runtimes have to match the processor. So you do not need an x86 target as if you write a native C/C++ SmartDevice project.
To your comments:
a) CF1.0 is installed on the device.
b) the exe built on the colleagues computer seems to be built for CF1 and therefor runs OK.
c) your exe is built for CF 3.5 and does not run as there is no CF3.5 runtime on the device.
d) most CF exe files are very small as long as they do not include large resources or ...
Conclusion so far: Install the CF3.5 runtime onto the device: http://msdn.microsoft.com/en-us/library/bb788171%28v=vs.90%29.aspx.
To run the legacy app on both devices, the referenced Motorola or other 3rd party runtimes must also be installed. I stringly recommand to setup your environment so you can use ActiveSync/WMDC for development, deployment and debugging of the device. If you are unable look for some more experienced colleague.
Can you try to run it inside the debugger and check where it fails?
Can you place a breakpoint right at the beginning of Program.main and check if it's reached?
Debug output may also give you some interesting hints.

8051 include file setting in eclipse

I am running Eclispe IDE Kepler C/C++Developers, because I would like to programming a 8051 based microcontroller. I start Eclipse, File>New>C Project. Select MCS51 family (SDCC) under Project type and SDCC Tool Chain under Toolchains. Click next, leave Release and Debug selected, click Finish. The project is created. I want to try a simple code:
#include <8051.h>
void delay()
{
int i,j;
for (i = 0;i<=100;i++)
for (j = 0;j<=100;j++);
}
void main()
{
while (1)
{
P1_0 =0; // led glow
delay();
P1_0 = 1; // led off
delay();
}
}
When I build it there was a question mark before #inlude<8051.h> , and when I double click on it, I had got a messsage: No Inludes Found, "No include files were found that matched that name."
So, as I think Eclipse did not find the 8051 header file. I tried to find an example how to solve this problem, but I failed. The question is how to set the right path for 8051.h? If anyone of you can offer me a right solution I would be greatful.
Inside the folder where the toolchain is installed, you should have a folder called "include". Check if 8051.h is in the "root" folder, inside /include. If not, look for it. You must add the path to the include. Let's say the file is in /arch/8051.h, your include becomes:
#include <arch/8051.h>
void delay()
{
//stuff

How to ping meter with Modbus

I am trying to ping a Socomec meter using the Modbus protocol, having researched, I found NModbus, a C# library. I have never used libraries or C# before (normally Java), but I have to dive right in.
I set myself up with Visual Studio Express for C# and installed .Net. I have copied then contents of the NModbus file into my project folder and added the references to the two main DLLs. Its didn't work with .Net 4, but I retargeted to 3.5 (and removed the Microsoft.Csharp reference) and things seemed to compile.
I am using this sample, below, to attempt to connect to the slave device. When I run this, and set the startAdress variable to the desired one (found in Socomec documentation) however all I get is a blank console window.
In short, am I using the correct method/parameters, is my setup/code incorrect? How do I connect to this meter?
My code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Ports;
using Modbus.Data;
using Modbus.Device;
using Modbus.Utility;
namespace NModbus
{
class SerialMaster
{
static void Main(string[] args)
{
ModbusSerialAsciiMasterReadRegisters();
}
public static void ModbusSerialAsciiMasterReadRegisters()
{
using (SerialPort port = new SerialPort("COM1"))
{
// configure serial port
port.BaudRate = 9600;
port.DataBits = 8;
port.Parity = Parity.None;
port.StopBits = StopBits.One;
port.Open();
// create modbus master
IModbusSerialMaster master = ModbusSerialMaster.CreateAscii(port);
byte slaveId = 1;
ushort startAddress = 50536;
ushort numRegisters = 5;
// read five registers
ushort[] registers = master.ReadHoldingRegisters(slaveId, startAddress, numRegisters);
for (int i = 0; i < numRegisters; i++)
Console.WriteLine("Register {0}={1}", startAddress + i, registers[i]);
Console.ReadLine();
}
// output:
// Register 1=0
// Register 2=0
// Register 3=0
// Register 4=0
// Register 5=0
}
}
}
Why don't you use some Java MODBUS library when you are already familiar with Java? I haven't worked with Socomec meters, but in general for MODBUS devices you need to know the protocol and addresses you are interested in. Then try to read tags from the device with some tool that you know is working well, like MODPOLL. Then when you get usable values as expected, you go to programming the polling connection in any language you like. Otherwise, you risk to loose a lot of time wondering what's going on.
One hint... From your code I see that you are acting as MODBUS ASCII serial master. Although such devices exist, 95% of RS232/RS485 devices I worked with were MODBUS RTU. Read specification if you don't know the difference.
You can run Java applications as a Windows service. There is a Tomcat Java service starter that I use with my company's Java application. You have create a method that will be called to stop the service, but that's just a method.
Here's the line I use to install my application as a service --
"%~dp0windows\tomcat6" //IS//%1 --DisplayName %1 --Description "gmServer for %1" ^
--JavaHome "%JAVA_HOME%" --Classpath "%PR_CLASSPATH%" --LogPrefix gmserver ^
--StartMode jvm --StopMode jvm --Jvm auto --StartPath "%~dp0." ^
--LogPath "%~dp0." --LogLevel debug --StdOutput %1.out --StdError %1.err ^
--StartClass greenMonitor.gmServer --StartParams -I#%I#-u#3600 ^
--StopMethod windowsService --StopParams stop --StopTimeout 10
The caret characters ("^") are line continuations characters in .BAT files. You should be able to find the meanings of the Tomcat command line options with the Tomcat documentation.
And for a Java-based Modbus library, complete with lots of handy programs you can use to test the connection, check out j2mod on Sourceforge. My company did a fork of jamod, along with a bunch of cleanups and that was the result.