Skip to content

Commit dc583a0

Browse files
Stephen HodgsonStephen Hodgson
authored andcommitted
Fixes material memory leaks in various files
1 parent 11f0e24 commit dc583a0

File tree

7 files changed

+71
-43
lines changed

7 files changed

+71
-43
lines changed

Assets/HoloToolkit/Input/Tests/Scripts/FocusedObjectColorChanger.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,29 @@ namespace HoloToolkit.Unity.InputModule.Tests
66
/// FocusedObjectMessageReceiver class shows how to handle focus events.
77
/// This particular implementatoin controls object appearance by changing its color when focused.
88
/// </summary>
9+
[RequireComponent(typeof(Renderer))]
910
public class FocusedObjectColorChanger : MonoBehaviour, IFocusable
1011
{
11-
[Tooltip("Object color changes to this when focused.")] public Color FocusedColor = Color.red;
12+
[Tooltip("Object color changes to this when focused.")]
13+
public Color FocusedColor = Color.red;
1214

13-
private Material material;
1415
private Color originalColor;
16+
private Material cachedMaterial;
1517

16-
private void Start()
18+
private void Awake()
1719
{
18-
material = GetComponent<Renderer>().material;
19-
originalColor = material.color;
20+
cachedMaterial = GetComponent<Renderer>().sharedMaterial;
21+
originalColor = cachedMaterial.GetColor("_Color");
2022
}
2123

2224
public void OnFocusEnter()
2325
{
24-
material.color = FocusedColor;
26+
cachedMaterial.SetColor("_Color", FocusedColor);
2527
}
2628

2729
public void OnFocusExit()
2830
{
29-
material.color = originalColor;
31+
cachedMaterial.SetColor("_Color", originalColor);
3032
}
3133
}
3234
}

Assets/HoloToolkit/Input/Tests/Scripts/SelectedObjectMessageReceiver.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,29 @@ namespace HoloToolkit.Unity.InputModule.Tests
66
/// SelectedObjectMessageReceiver class shows how to handle messages sent by SelectedObjectMessageSender.
77
/// This particular implementatoin controls object appearance by changing its color when selected.
88
/// </summary>
9+
[RequireComponent(typeof(Renderer))]
910
public class SelectedObjectMessageReceiver : MonoBehaviour
1011
{
11-
[Tooltip("Object color changes to this when selected.")] public Color SelectedColor = Color.red;
12+
[Tooltip("Object color changes to this when selected.")]
13+
public Color SelectedColor = Color.red;
1214

13-
private Material material;
1415
private Color originalColor;
16+
private Material cachedMaterial;
1517

16-
private void Start()
18+
private void Awake()
1719
{
18-
material = GetComponent<Renderer>().material;
19-
originalColor = material.color;
20+
cachedMaterial = GetComponent<Renderer>().sharedMaterial;
21+
originalColor = cachedMaterial.GetColor("_Color");
2022
}
2123

2224
public void OnSelectObject()
2325
{
24-
material.color = SelectedColor;
26+
cachedMaterial.SetColor("_Color", SelectedColor);
2527
}
2628

2729
public void OnClearSelection()
2830
{
29-
material.color = originalColor;
31+
cachedMaterial.SetColor("_Color", originalColor);
3032
}
3133
}
3234
}

Assets/HoloToolkit/Input/Tests/Scripts/SphereGlobalKeywords.cs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,35 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License. See LICENSE in the project root for license information.
33

4-
using System;
54
using UnityEngine;
65

76
namespace HoloToolkit.Unity.InputModule.Tests
87
{
98
public class SphereGlobalKeywords : MonoBehaviour, ISpeechHandler
109
{
10+
private Material[] cachedChildMaterials;
11+
12+
private void Awake()
13+
{
14+
Renderer[] childRenderers = GetComponentsInChildren<Renderer>();
15+
if (childRenderers != null && childRenderers.Length > 0)
16+
{
17+
cachedChildMaterials = new Material[childRenderers.Length];
18+
for (int i = 0; i < childRenderers.Length; i++)
19+
{
20+
cachedChildMaterials[i] = childRenderers[i].sharedMaterial;
21+
}
22+
}
23+
}
24+
1125
public void OnSpeechKeywordRecognized(SpeechKeywordRecognizedEventData eventData)
1226
{
1327
switch (eventData.RecognizedText.ToLower())
1428
{
1529
case "reset all":
16-
foreach (Renderer renderer in GetComponentsInChildren<Renderer>())
30+
foreach (Material cachedChildMaterial in cachedChildMaterials)
1731
{
18-
renderer.material.color = Color.gray;
32+
cachedChildMaterial.SetColor("_Color", Color.gray);
1933
}
2034
break;
2135
}

Assets/HoloToolkit/Input/Tests/Scripts/SphereKeywords.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,32 @@
11
// Copyright (c) Microsoft Corporation. All rights reserved.
22
// Licensed under the MIT License. See LICENSE in the project root for license information.
33

4-
using System;
54
using UnityEngine;
65

76
namespace HoloToolkit.Unity.InputModule.Tests
87
{
8+
[RequireComponent(typeof(Renderer))]
99
public class SphereKeywords : MonoBehaviour, ISpeechHandler
1010
{
11+
private Material cachedMaterial;
12+
13+
private void Awake()
14+
{
15+
cachedMaterial = GetComponent<Renderer>().sharedMaterial;
16+
}
17+
1118
public void ChangeColor(string color)
1219
{
1320
switch (color.ToLower())
1421
{
1522
case "red":
16-
GetComponent<Renderer>().material.color = Color.red;
23+
cachedMaterial.SetColor("_Color", Color.red);
1724
break;
1825
case "blue":
19-
GetComponent<Renderer>().material.color = Color.blue;
26+
cachedMaterial.SetColor("_Color", Color.blue);
2027
break;
2128
case "green":
22-
GetComponent<Renderer>().material.color = Color.green;
29+
cachedMaterial.SetColor("_Color", Color.green);
2330
break;
2431
}
2532
}

Assets/HoloToolkit/Input/Tests/Scripts/TestButton.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ public class TestButton : MonoBehaviour, IInputClickHandler, IFocusable
3333
public bool EnableActivation = true;
3434

3535
private AnimatorControllerParameter[] animatorHashes;
36+
private Material cachedToolTipMaterial;
3637

3738
private bool focused;
3839
public bool Focused
@@ -101,13 +102,14 @@ protected virtual void Awake()
101102

102103
protected virtual void OnEnable()
103104
{
104-
105105
// Set the initial alpha
106106
if (ToolTipRenderer != null)
107107
{
108-
Color tipColor = ToolTipRenderer.material.color;
108+
cachedToolTipMaterial = ToolTipRenderer.sharedMaterial;
109+
110+
Color tipColor = cachedToolTipMaterial.GetColor("_Color");
109111
tipColor.a = 0.0f;
110-
ToolTipRenderer.material.color = tipColor;
112+
cachedToolTipMaterial.SetColor("_Color", tipColor);
111113
toolTipTimer = 0.0f;
112114
}
113115

@@ -135,9 +137,9 @@ private void Update()
135137
// Update the new opacity
136138
if (ToolTipRenderer != null)
137139
{
138-
Color tipColor = ToolTipRenderer.material.color;
140+
Color tipColor = cachedToolTipMaterial.GetColor("_Color");
139141
tipColor.a = Mathf.Clamp(toolTipTimer, 0, ToolTipFadeTime) / ToolTipFadeTime;
140-
ToolTipRenderer.material.color = tipColor;
142+
cachedToolTipMaterial.SetColor("_Color", tipColor);
141143
}
142144
}
143145
}

Assets/HoloToolkit/Sharing/Scripts/Utilities/Utils.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,22 +112,29 @@ public static void SetMaterialRecursive(Transform t, Material mat)
112112
}
113113

114114
/// <summary>
115-
/// Change material for every object in hierarchy which has a name equal to nameToTest
115+
/// Change material for every object in hierarchy which has a name equal to nameToTest.
116+
/// http://answers.unity3d.com/questions/548420/material-memory-leak.html
117+
/// This function automatically instantiates the materials and makes them unique to this renderer.
118+
/// It is your responsibility to destroy the materials when the game object is being destroyed.
119+
/// Resources.UnloadUnusedAssets also destroys the materials but it is usually only called when loading a new level.
120+
/// https://docs.unity3d.com/ScriptReference/Renderer-material.html
116121
/// </summary>
117122
/// <param name="t">root transform to start looking for renderers</param>
118123
/// <param name="mat">material to set everything to</param>
119-
/// <param name="ignoreName">ignore GameObjects with this name</param>
124+
/// <param name="nameToTest">ignore GameObjects with this name</param>
120125
public static void SetMaterialRecursiveForName(Transform t, Material mat, string nameToTest)
121126
{
122127
if (t.gameObject && t.gameObject.GetComponent<Renderer>() && t.gameObject.name == nameToTest)
123128
{
124-
t.gameObject.GetComponent<Renderer>().material = mat;
129+
t.gameObject.GetComponent<Renderer>().sharedMaterial = mat;
125130
}
126131

127132
for (int ii = 0; ii < t.childCount; ++ii)
128133
{
129134
SetMaterialRecursiveForName(t.GetChild(ii), mat, nameToTest);
130135
}
136+
137+
Resources.UnloadUnusedAssets();
131138
}
132139

133140
/// <summary>

Assets/HoloToolkit/Utilities/Scripts/DirectionIndicator.cs

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,12 @@ public void Awake()
5555
if (DirectionIndicatorObject == null)
5656
{
5757
Debug.LogError("Direction Indicator failed to instantiate.");
58-
return;
5958
}
6059
}
6160

6261
public void OnDestroy()
6362
{
64-
GameObject.Destroy(DirectionIndicatorObject);
63+
Destroy(DirectionIndicatorObject);
6564
}
6665

6766
private GameObject InstantiateDirectionIndicator(GameObject directionIndicator)
@@ -81,17 +80,17 @@ private GameObject InstantiateDirectionIndicator(GameObject directionIndicator)
8180
directionIndicatorRenderer.enabled = false;
8281

8382
// Remove any colliders and rigidbodies so the indicators do not interfere with Unity's physics system.
84-
foreach (Collider collider in indicator.GetComponents<Collider>())
83+
foreach (Collider indicatorCollider in indicator.GetComponents<Collider>())
8584
{
86-
Destroy(collider);
85+
Destroy(indicatorCollider);
8786
}
8887

8988
foreach (Rigidbody rigidBody in indicator.GetComponents<Rigidbody>())
9089
{
9190
Destroy(rigidBody);
9291
}
9392

94-
Material indicatorMaterial = directionIndicatorRenderer.material;
93+
Material indicatorMaterial = directionIndicatorRenderer.sharedMaterial;
9594
indicatorMaterial.color = DirectionIndicatorColor;
9695
indicatorMaterial.SetColor("_TintColor", DirectionIndicatorColor);
9796

@@ -132,14 +131,11 @@ private bool IsTargetVisible()
132131
// This will return true if the target's mesh is within the Main Camera's view frustums.
133132
Vector3 targetViewportPosition = Camera.main.WorldToViewportPoint(gameObject.transform.position);
134133
return (targetViewportPosition.x > VisibilitySafeFactor && targetViewportPosition.x < 1 - VisibilitySafeFactor &&
135-
targetViewportPosition.y > VisibilitySafeFactor && targetViewportPosition.y < 1 - VisibilitySafeFactor &&
136-
targetViewportPosition.z > 0);
134+
targetViewportPosition.y > VisibilitySafeFactor && targetViewportPosition.y < 1 - VisibilitySafeFactor &&
135+
targetViewportPosition.z > 0);
137136
}
138137

139-
private void GetDirectionIndicatorPositionAndRotation(
140-
Vector3 camToObjectDirection,
141-
out Vector3 position,
142-
out Quaternion rotation)
138+
private void GetDirectionIndicatorPositionAndRotation(Vector3 camToObjectDirection, out Vector3 position, out Quaternion rotation)
143139
{
144140
// Find position:
145141
// Save the cursor transform position in a variable.
@@ -160,9 +156,7 @@ private void GetDirectionIndicatorPositionAndRotation(
160156
position = origin + cursorIndicatorDirection * MetersFromCursor;
161157

162158
// Find the rotation from the facing direction to the target object.
163-
rotation = Quaternion.LookRotation(
164-
Camera.main.transform.forward,
165-
cursorIndicatorDirection) * directionIndicatorDefaultRotation;
159+
rotation = Quaternion.LookRotation(Camera.main.transform.forward, cursorIndicatorDirection) * directionIndicatorDefaultRotation;
166160
}
167161
}
168162
}

0 commit comments

Comments
 (0)