Bạn đang gặp phải tình trạng khó chịu khi các thay đổi về vật liệu phát sáng (emissive material) bạn thực hiện trong Unity Editor bị mất sau khi lưu scene? Đừng lo lắng, bài viết này sẽ cung cấp cho bạn giải pháp chi tiết và dễ hiểu để khắc phục vấn đề này. Chúng ta sẽ đi sâu vào nguyên nhân gây ra lỗi, cách sử dụng code và các thiết lập shader để đảm bảo hiệu ứng phát sáng (glow effect) của bạn được giữ nguyên sau khi lưu.
Lỗi này thường xảy ra do cách Unity quản lý các thay đổi đối với tài sản (assets) trong project. Khi bạn thay đổi thuộc tính của một material thông qua script trong editor, Unity có thể không tự động lưu những thay đổi này vào file asset. Điều này dẫn đến việc khi bạn lưu scene, material sẽ trở về trạng thái ban đầu của nó.
Một nguyên nhân khác có thể là do thiết lập shader không chính xác, đặc biệt là khi bạn sử dụng các custom shader. Nếu các thuộc tính emission không được khai báo đúng cách trong shader, Unity sẽ không thể lưu chúng một cách chính xác.
EditorUtility.SetDirty()
và AssetDatabase.SaveAssetIfDirty()
Đây là cách phổ biến nhất để đảm bảo Unity lưu các thay đổi của bạn. Sau khi bạn thay đổi thuộc tính của material, hãy gọi hai hàm này để báo cho Unity biết rằng material đã bị thay đổi và cần được lưu lại.
Ví dụ:
using UnityEditor;
using UnityEngine;
public class GlowEffectHandler : MonoBehaviour
{
[SerializeField]
private Material glowMaterial;
[SerializeField]
private bool isEmissionEnabled;
private void OnValidate()
{
if (glowMaterial != null)
{
if (isEmissionEnabled)
{
glowMaterial.EnableKeyword("_EMISSION");
}
else
{
glowMaterial.DisableKeyword("_EMISSION");
}
// Đánh dấu material là đã thay đổi
EditorUtility.SetDirty(glowMaterial);
// Lưu material nếu nó đã bị thay đổi
AssetDatabase.SaveAssetIfDirty(glowMaterial);
}
}
}
Lưu ý: Đoạn code trên sử dụng `OnValidate()`, hàm này chỉ chạy trong Editor. Để đảm bảo tính năng hoạt động trong build, bạn cần có thêm logic để xử lý việc bật/tắt emission khi runtime.
Undo.RecordObject()
Hàm này cho phép bạn ghi lại trạng thái của một object trước khi thực hiện thay đổi. Điều này rất hữu ích nếu bạn muốn hỗ trợ chức năng Undo/Redo trong editor.
Ví dụ:
using UnityEditor;
using UnityEngine;
public class GlowEffectHandler : MonoBehaviour
{
[SerializeField]
private Material glowMaterial;
[SerializeField]
private bool isEmissionEnabled;
#if UNITY_EDITOR
private void OnValidate()
{
// Ghi lại trạng thái của material trước khi thay đổi
Undo.RecordObject(glowMaterial, "Toggle Glow");
EditorUtility.SetDirty(glowMaterial);
if (isEmissionEnabled)
{
glowMaterial.EnableKeyword("_EMISSION");
}
else
{
glowMaterial.DisableKeyword("_EMISSION");
}
}
#endif
}
Lưu ý: Code này sử dụng `#if UNITY_EDITOR` để đảm bảo chỉ biên dịch trong môi trường Unity Editor, tránh gây lỗi khi build game.
Nếu bạn sử dụng **custom shader**, hãy đảm bảo bạn đã khai báo các thuộc tính liên quan đến emission trong phần `Properties` của shader. Nếu không, Unity sẽ không biết cách lưu các giá trị này.
Ví dụ:
Shader "Custom/EmissiveShader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_EmissionColor ("Emission Color", Color) = (1,1,1,1)
_EmissionIntensity ("Emission Intensity", Float) = 1.0
}
SubShader
{
// ... (phần còn lại của shader) ...
}
}
Đôi khi, vật liệu emissive có thể không phát sáng như mong đợi nếu không được thiết lập đúng chế độ **Lighting**. Hãy đảm bảo rằng vật liệu được đánh dấu là "Static" hoặc "Lightmap Static" trong Inspector, và chế độ "Global Illumination" được đặt phù hợp (ví dụ: "Realtime" hoặc "Baked"). Nếu bạn muốn vật liệu emissive ảnh hưởng đến các đối tượng động (dynamic geometry), hãy sử dụng **Light Probes**.
Hy vọng với những giải pháp trên, bạn sẽ có thể khắc phục thành công lỗi emissive material bị reset khi lưu scene trong Unity. Chúc bạn thành công!
Bài viết liên quan