forked from Unity-Technologies/UnityCsReference
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLazyLoadReference.cs
More file actions
148 lines (136 loc) · 6.24 KB
/
Copy pathLazyLoadReference.cs
File metadata and controls
148 lines (136 loc) · 6.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Unity C# reference source
// Copyright (c) Unity Technologies. For terms of use, see
// https://unity3d.com/legal/licenses/Unity_Reference_Only_License
using System;
using System.Runtime.InteropServices;
using UnityEngine.Scripting;
using UnityEngineInternal;
using uei = UnityEngine.Internal;
namespace UnityEngine
{
//----------------------------------------------------------------------------------------------------------------------
// What is this : Serializable lazy reference to a UnityEngine.Object contained in an asset file, where referenced object
// is loaded only when accessed and not at deserialization of this struct.
// Motivation(s):
// - Importer settings need to be able to reference assets but reading the settings from disk Must Not load the referenced
// assets: they may not have been imported yet.
// - Scenes with large number of assets can be slow to open because all referenced assets get loaded at the same time
// as the scene, even if they are not needed right away. Having lazy loading can make loading scene faster for the user.
// For example: MonoBehaviours that have references to assets but that do not execute in editor mode, do not need to have
// all the referenced assets loaded when editor opens a scene. Later when user enters play mode, those assets get loaded.
//
// Notes:
// - *** The memory layout of this struct must be identical to the native type: AssetReferenceMemoryLayout. ***
// - Not using bindings file as we don't want a wrapper class in this situation. but it must mirror it's native counter part to a 'T'.
//----------------------------------------------------------------------------------------------------------------------
/// <summary>
/// Serializable lazy reference to a <see cref="UnityEngine.Object"/> contained in an asset file, where referenced object is loaded only when accessed and not at deserialization of this struct.
/// </summary>
/// <typeparam name="T">The type of the asset.</typeparam>
[Serializable, StructLayout(LayoutKind.Sequential)]
public struct LazyLoadReference<T> where T : UnityEngine.Object
{
private const int kInstanceID_None = 0;
[SerializeField]
private int m_InstanceID;
/// <summary>
/// Determines if the reference is linked to an asset, loaded or not, valid or not.
/// Calling this never triggers a load.
/// </summary>
public bool isSet => m_InstanceID != kInstanceID_None;
/// <summary>
/// Convenience property that checks if the reference is broken: is set to something, but that something is not available/loadable at the moment for whatever reason.
/// May trigger loading the referenced object into memory if the object is not already loaded.
/// </summary>
public bool isBroken => m_InstanceID != kInstanceID_None && !UnityEngine.Object.DoesObjectWithInstanceIDExist(m_InstanceID);
/// <summary>
/// Accessor to the referenced asset.
/// May trigger loading the referenced object into memory if the object is not already loaded.
/// </summary>
public T asset
{
get
{
if (m_InstanceID == kInstanceID_None)
{
return null;
}
else
{
return (T)Object.ForceLoadFromInstanceID(m_InstanceID);
}
}
set
{
if (value == null)
{
m_InstanceID = kInstanceID_None;
}
else
{
if (!Object.IsPersistent(value))
{
throw new ArgumentException("Object that does not belong to a persisted asset cannot be set as the target of a LazyLoadReference.");
}
m_InstanceID = value.GetInstanceID();
}
}
}
/// <summary>
/// InstanceID of the referenced asset.
/// Getting or setting this never triggers a load.
/// </summary>
public int instanceID
{
get => m_InstanceID;
set => m_InstanceID = value;
}
/// <summary>
/// Construct a <see cref="LazyLoadReference{T}"/> from asset reference.
/// May trigger loading the referenced object into memory if the object is not already loaded.
/// </summary>
/// <param name="asset"></param>
public LazyLoadReference(T asset)
{
if (asset == null)
{
m_InstanceID = kInstanceID_None;
}
else
{
if (!Object.IsPersistent(asset))
{
throw new ArgumentException("Object that does not belong to a persisted asset cannot be set as the target of a LazyLoadReference.");
}
m_InstanceID = asset.GetInstanceID();
}
}
/// <summary>
/// Construct a <see cref="LazyLoadReference{T}"/> from asset instance ID.
/// Calling this never triggers a load.
/// </summary>
/// <param name="instanceID"></param>
public LazyLoadReference(int instanceID)
{
m_InstanceID = instanceID;
}
/// <summary>
/// Implicit conversion from <see cref="T"/> asset to <see cref="LazyLoadReference{T}"/>.
/// May trigger loading the referenced object into memory if the object is not already loaded.
/// </summary>
/// <param name="asset">The asset reference.</param>
public static implicit operator LazyLoadReference<T>(T asset)
{
return new LazyLoadReference<T> { asset = asset };
}
/// <summary>
/// Implicit conversion from asset instance ID to <see cref="LazyLoadReference{T}"/>.
/// Calling this never triggers a load.
/// </summary>
/// <param name="instanceID">The asset instance ID.</param>
public static implicit operator LazyLoadReference<T>(int instanceID)
{
return new LazyLoadReference<T> { instanceID = instanceID };
}
}
}