Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Serialize Light2Ds to ScriptableObjects?

Discussion in '2D' started by Avalin, Jun 19, 2023.

  1. Avalin

    Avalin

    Joined:
    Oct 12, 2018
    Posts:
    98
    Is it in any way possible to do this?

    What I want to achieve is to define the freeform shape, intensity, sorting layer, falloffIntensity, color etc. and then in editor time, instantiate the lights i've defined from a Scriptable Object.

    Currently i make new prefabs for each object needing lights, and add light2D on empty gameobjects in said prefab, shape the freeforms to my liking, and add that to my scriptable object. Not super flexible in the long run. I think the biggest hurdle is the vector shapePath and setting/creating those on my freeform lights using scriptable objects. if I could just copy and paste the shapepoints to my SO as is possible with PolygonColliders it'd be great. (And obviously setting them on a dynamically created Light2D)
     
    Last edited: Jun 20, 2023
  2. Avalin

    Avalin

    Joined:
    Oct 12, 2018
    Posts:
    98
    Does no one have a genius solution to this or a workaround?
     
  3. Chris-Trueman

    Chris-Trueman

    Joined:
    Oct 10, 2014
    Posts:
    1,256
  4. Avalin

    Avalin

    Joined:
    Oct 12, 2018
    Posts:
    98
    Thanks for your response!
    Although, I didn't have much success with it. :(
    I am using Unity 2021.3.17f1 at the moment.

    The debug.log I added here does return a count of "4", so it did acknowledge the vectors I inserted. (I even printed the vectors themselves, they look fine)
    However when I press the "Edit Shape" in Unity, it shows only one vector point (0, 0, which I assume is default)
    It also isn't reflected in playmode. (Another interesting thing about this bug(?) is that I am unable to move the default point at 0, 0. If I set a different value, it keeps the serialized values, but it still shows the point at 0, 0. Under normal circumstances, when a light2D isn't instantiated, I have no problems moving a point by changing the values)

    Here's my code:

    Code (CSharp):
    1.     public class TileDecorationLight : MonoBehaviour
    2.     {
    3.         [SerializeField] private new Light2D light;
    4.  
    5.         public void Setup(Light2DData lightData)
    6.         {
    7.             name = lightData.LightName;
    8.             switch (lightData)
    9.             {
    10.                 case FreeformLight2DData freeformData:
    11.                     freeformData.SetupLight2D(light);
    12.                     Debug.Log(light.shapePath.Length);
    13.                     break;
    14.  
    15.                 case SpriteLight2DData spriteData:
    16.                     spriteData.SetupLight2D(light);
    17.                     break;
    18.  
    19.                 case SpotLight2DData spotData:
    20.                     spotData.SetupLight2D(light);
    21.                     break;
    22.  
    23.                 default:
    24.                     throw new Exception("Incorrect LightType used.");
    25.             }
    26.        
    27.             lightData.SetupLight2D(light);
    28.         }
    29.     }
    30.  
    31.     [Serializable]
    32.     public class FreeformLight2DData : Light2DData
    33.     {
    34.         [Header("Freeform")]
    35.         [SerializeField] private float falloff;
    36.         [SerializeField] private List<Vector2> freeformShape;
    37.  
    38.         public override Light2D.LightType LightType => Light2D.LightType.Freeform;
    39.  
    40.         public override Light2D SetupLight2D(Light2D light)
    41.         {
    42.             Light2D light2D = base.SetupLight2D(light);
    43.             light2D.SetShapePath(freeformShape.Select(vector2 => new Vector3(vector2.x, vector2.y, 0f)).ToArray());
    44.             light2D.SetFreeformFalloff(falloff);
    45.             return light2D;
    46.         }
    47.     }
    48.  
    49.     [Serializable]
    50.     public abstract class Light2DData
    51.     {
    52.         [Header("General")]
    53.         [SerializeField] protected string lightName = "1";
    54.         [SerializeField] protected Color color = Color.white;
    55.         [SerializeField] protected float intensity = 1f;
    56.         [SerializeField] [Range(0f, 1f)] protected float falloffStrength = 0.5f;
    57.         [SerializeField] protected SortingLayerSelector targetSortingLayers;
    58.    
    59.         [Header("Transform")]
    60.         [SerializeField] protected Vector2 localPosition;
    61.         [SerializeField] protected Vector2 localScale;
    62.  
    63.         public string LightName => lightName;
    64.         public abstract Light2D.LightType LightType { get; }
    65.    
    66.         public virtual Light2D SetupLight2D(Light2D light)
    67.         {
    68.             light.lightType = LightType;
    69.             light.transform.localPosition = localPosition;
    70.             light.transform.localScale = localScale;
    71.             light.color = color;
    72.             light.intensity = intensity;
    73.             light.falloffIntensity = falloffStrength;
    74.             light.SetTargetSortingLayers(targetSortingLayers.SelectedLayerIDs);
    75.             return light;
    76.         }
    77.     }
     
    Last edited: Jun 21, 2023
  5. Chris-Trueman

    Chris-Trueman

    Joined:
    Oct 10, 2014
    Posts:
    1,256
    I would submit a bug report, everything looks fine in your code. I can't test it in 2021.3.12 as the method doesn't exist, which it should according to the docs. It shows it was added with URP 12.1.12, the highest version I can get with 2021.3.12 is 12.1.7.

    Something isn't right, maybe they added the method but it doesn't actually update the light properly. I've had issues with the 2D lighting and have had to rethink some projects. Mostly due to bugs that might be fixed in tech releases.
     
  6. Chris-Trueman

    Chris-Trueman

    Joined:
    Oct 10, 2014
    Posts:
    1,256
    I can confirm this works in the latest LTS 2022.3.2f1

    When editing the shape in the editor it only will show you the current point you are manipulating, it does not work the same as a polygon editor.

    Here is the test code I used. Once you apply the path pressing L, modifying the array in the editor will update the light path automatically(it is passed in as a reference after all.)

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.Rendering.Universal;
    5.  
    6. [RequireComponent(typeof(Light2D))]
    7. public class LightTest : MonoBehaviour
    8. {
    9.     public Vector3[] lightShapePoints;
    10.  
    11.     private Light2D _light;
    12.  
    13.     // Start is called before the first frame update
    14.     void Start()
    15.     {
    16.         _light = GetComponent<Light2D>();
    17.         _light.lightType = Light2D.LightType.Freeform;
    18.     }
    19.  
    20.     // Update is called once per frame
    21.     void Update()
    22.     {
    23.         if (Input.GetKeyDown(KeyCode.L))
    24.         {
    25.             _light.SetShapePath(lightShapePoints);
    26.         }
    27.     }
    28. }
     
    Avalin likes this.
  7. Avalin

    Avalin

    Joined:
    Oct 12, 2018
    Posts:
    98
    Ah thank you. I also learnt another valuable lesson when instantiating Light2D objects:
    Ensure that the GameObject does not have Scale (0, 0, 0). Makes it very hard to modify :D I set it to scale (1, 1, 1) and all the points was showing :oops: