0

Is there a way to tell if a project is used by Unity whether that be compiled to XBOX, Windows, Android... or still in the editor

I am creating a class that will allow either System.Numerics.Vector3 or UnityEngine.Vector3 based on whether or not UnityEngine is available, but it needn't be platform dependent just from or in Unity, I am creating a set of extensions that I want to be able to use inside and outside of Unity without having to define custom #define UNITY

I have no way to compile for many platforms so is it as easy as #if UNITY_5

To Clarify what I an looking for the software I am creating is NOT going to be exlusively used within a Unity Project, It is being designed to run virtually anywhere, Unity, UWP, WFP, Windows Console etc.

  • This is not dependant compilation, but dependant execution. | Usually you just pick the thing that is avalible on both side under guarantee. Unity was designed to be cross-platform, so I would asume it is always there. The way for cross platform is finding the "smalest common denominator". – Christopher May 24 '20 at 22:19
  • Fair enough I suppose I do want dependant excecution, is there a way to tell if UnityEngine.Vector3 exists for use and if not to just use System.Numerics.Vector3, the methods that require the use of the Vectors return floats which both Vector structs use. –  May 24 '20 at 22:26
  • Why would you create a project with Unity if the namespace `UnityEngine` will not be available?? The `UnityEngine` namespace will be included in any project made with Unity on any target platform ... it is the core of the entire Engine so why should it not be available? – derHugo May 25 '20 at 08:04
  • The purpose is a cross platform library that's uses Vector Math, in Unity that's its built in Vectors and outside of Unity that's System.Numerics, while UnityEngine is available I want to use Unitys Vector, and if it's not available I want to use System.Numerics –  May 26 '20 at 01:01

3 Answers3

1

You can check out platform dependent compilation on Unity docs - https://docs.unity3d.com/Manual/PlatformDependentCompilation.html

I think that might be what you're looking for. They already have bunch of premade directives ready for use so you don't have to invent your own.

Example:

#if UNITY_EDITOR
            // Do some stuff
#elif UNITY_STANDALONE_WIN
            // Do some stuff
#endif
Quickz
  • 1,626
  • 2
  • 11
  • 21
  • I have looked at this page, but I am hoping to not have to write multiple `#if` statments just to check if we are in the editor, or any compiled platform of unity, I was hoping for a catchall `#if UnityCreated` type define –  May 24 '20 at 22:32
1

I am creating a class that will allow either System.Numerics.Vector3 or UnityEngine.Vector3 based on whether or not UnityEngine is available, but it needn't be platform dependent just from or in Unity

The usual way to do cross-platform, is to find the "smalest common denominator". Unity was designed to be cross-platform. And vectors are a core type for every game engine. .NET was a late adopter of Vector3, only getting it in Framework 4.6/Standart 2.1. But again, for a 3D game engine it is a fundamental piece. So I would bet real money on UnityEngine.Vector3 being avalible in every version of the Unity engine.

If that is somehow not the case? Just write your own Vector3. It is a struct with 3 numbers - not exactly a hard thing to copy. Here is a example one:

//structs should be inmutable. readonly makes sure of that
public readonly struct Vector3 {
    int X;
    int Y;
    int Z;
}

I asumed it is integers, but apparently the vector classes actually use Single - a 32-bit float type. But the precise type is a trivial difference.

Christopher
  • 9,634
  • 2
  • 17
  • 31
  • Why `//structs should be inmutable.`? Unity's build in [`Vector3`](https://docs.unity3d.com/ScriptReference/Vector3.html) (and yes these should be `float`) clearly is **not** and there are many many use-cases where you want to change an individual component of a vector without wanting to create a new instance of it. (Anyway *if* you make it `readonly` all its fields also would need to be `readonly`) – derHugo May 25 '20 at 08:20
  • @derHugo It is not hard to answer this question with a google search: https://stackoverflow.com/questions/3751911/why-are-c-sharp-structs-immutable | https://learn.microsoft.com/en-us/dotnet/csharp/write-safe-efficient-code | https://theburningmonk.com/2010/04/net-tips-making-a-serializable-immutable-struct/ | https://www.codemag.com/Article/1905041/Immutability-in-C – Christopher May 25 '20 at 12:22
  • These look more like recommendations ... however I would not make a custom struct immutable if the actual type you are cloning is not .. this might lead to a lot compiler errors later when building for a different platform. Yes of course the performance argument is quite good but I would not simply assume that everyone wants immutable structs everywhere ;) Unity themselves quite often do things like `var position = transform.position; position.y = 0; transform.position = position;` just as an example. With your recommendations you actually allocate more memory just to do so ... – derHugo May 25 '20 at 12:29
0

Not quite sure why the UnityEngine namespace should not not exist in any Unity made project - on any target platform.

It is the main engine core so why do you think it should not be there?


Pre-Processor that covers any Unity version (since 5.3.4)

Anyway from using the general #if pre-processors (See Unity Manual - Platform dependent compilation) starting from Unity version 5.3.4 you can check whether you are in any Unity version by simply using

#if UNITY_5_3_OR_NEWER
    // Use UnityEngine
#else
    // Use something else
#endif

which as the name says covers all Unity versions above 5.3.4 and any project/app built with it regardless of the target device.


Use a global define

Also instead of your own

#define UNITY

in each and every script you can go to the Player Settings (Edit → Project Settings → Player) and add your own global custom define in the Unity Editor (and a build of course) for all scripts:

Open the Other Settings panel of the Player Settings and navigate to the Scripting Define Symbols text box.

enter image description here

Here you can add a ;-separated list of your own global defines. There you could also simply enter UNITY and then use

#if UNITY
    // Use Unity stuff
#else
    // Use other stuff
#endif

Add global define automatically via Editor script

And now the cool thing: You can add such a global define also via editor script!

Therefore e.g. simply add a script in your library within a folder called Editor:

#if !YOURDEFINE
    // We only need this class once if the global define is not added yet
    // The above YOURDEFINE has to exactly match the DEFINE declared below
    // Once it is already defined in the PlayerSettings it stays defined permanently
    // so we don't need to run this class on every project load
    using UnityEngine;
    using UnityEditor;

    internal class StartUp
    {
        /// <summary> 
        /// The define to be added to the global defines list.
        /// <para>This needs to match exactly the #if pre-processor
        /// on top of this file!</para>
        /// </summary>
        private const DEFINE = "YOURDEFINE";

        /// <summary>
        /// automatically executed once the project is loaded and after
        /// every re-compile in the UnityEditor
        /// </summary>
        [InitializeOnLoadMethod]
        private static void Initialize()
        {
            // Get current defines from PlayerSettings
            var defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup);
            // Split into list at ';'
            var defineList = defines.Split(';').ToList();

            // Check if already contains your define
            // Actually this should never happen since if this is the case
            // The entire class should already be stripped of due to the 
            // pre-processor on top of this file
            // Therefore if this happens something is wrong
            if (defineList.Contains(Constants.Define))
            {
                Debug.LogError("Huh?! This should not happen! Please check the DEFINE const and the pro-processor on top of StartUp.cs!");
                return;
            }

            // if not simply append it
            // Unity doesn't care about a leading ;
            // if this is the first entry it is removed automatically
            defines += $";{DEFINE}";

            // This writes back the new defines and evtl. causes a re-compile
            // be careful with that though because if you mess it up
            // you might end up in a permanent re-compile ;)
            PlayerSettings.SetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup, defines);
        }
    }
#endif
derHugo
  • 83,094
  • 9
  • 75
  • 115
  • I understand that I am able to create my own Define in unity I was just wondering if there was an already existing version of the same thing. But wouldnt that compile the library I intend to make as if UnityEngine was not available? –  May 26 '20 at 01:03
  • Well as said in the answer: You can use `#if UNITY_5_3_OR_NEWER` which covers all Unity version from `5.3.4` up to now e.g. `2019.3.14` .. which would pretty much means **any Unity**. Or alterantively as also said in the answer: Simply add your own define in the player settings `UNITY` which is then also a global general define. Note: You can also add such a define via code if that's what you are after - just added it at the bottom – derHugo May 26 '20 at 06:34
  • yes but does it also cover the Build platforms as well –  May 26 '20 at 07:31
  • @RWolfe what do you mean? Which build platforms? As mentioned on top of the answer .. I think we all still don't really understand your concerns ... **every** project created with Unity will have the UnityEngine namespace and above mentioned defines ... regardless the target platform you compiled it for ... – derHugo May 26 '20 at 07:44
  • The software I am trying to make, is not designed to be exclusively used by Unity, It is designed to be used wherever, in Windows Console, Unity, UWP, WFP... which is why I can't rely on UnityEngine.VectorX all the time, I need it to be more versatile. –  May 27 '20 at 11:39
  • Yes so but so what is the problem with using either the global define in Unity or using the `#if UNITY_5_3_OR_NEWER` which would be true in all Unity made projects and builds to any target and not true on your other platforms? – derHugo May 27 '20 at 12:15
  • There isn't anything wrong with that method. I have very little understaning of the `#if` statements and even less when it applies to Unity, Unity's documentation on this is not very helpful at explaining what applies to what. –  May 27 '20 at 12:41
  • @RWolfe I hoped I did it explain for you ;) What do you not understand exactly? in general the `#if XXX` compiles your code only if the according define is existent. Unity automatically adds the defines you can see in their docs ... so as simple as if `UNITY_5_3_OR_NEWER` is defined (the case in any Unity version after 5.3.4 from some years ago until today) then it only compiles the code wrapped within the if block. Otherwise for any other platform/environment it compiles only the else block. – derHugo May 27 '20 at 14:00
  • Thank you, that is exactly what i didn't understand. I wasn't certain if `UNITY_5_3_OR_NEWER` would compile everything Unity compiled to. –  May 27 '20 at 19:09
  • Yes as I said, the `UNITY_5_3_OR_NEWER` is defined for every project opened and compiled with any Unity version above `5.3.4` regardless of the device you build for :) – derHugo May 28 '20 at 05:26