NodeBB

    • Login
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    1. Home
    2. changx
    3. Posts
    C
    • Profile
    • Following 0
    • Followers 0
    • Topics 5
    • Posts 9
    • Best 0
    • Controversial 0
    • Groups 1

    Posts made by changx

    • RE: Tổng hợp Optimize NATV

      https://learn.unity.com/tutorial/fixing-performance-problems-2019-3

      posted in Developer Discussion
      C
      changx
    • Tổng hợp Optimize NATV

      🧩Unity Performance Optimization (NATV)


      I. Giảm DrawCall

      ⚙️ Dùng SRP Batcher của URP

      Gom nhiều mesh có cùng shader vào 1 batch drawcall, giúp giảm đáng kể chi phí CPU khi render nhiều object như monster hoặc vật cản.

      Bật trong Project Settings → Graphics → SRP Batcher

      SRP Batcher Example


      🧱 Dùng chung Shader / Material / Layer

      • Chuyển các vật cản, nơi đứng của monster thành Spine Animation (shader: Universal Render Pipeline/2D/Spine/Skeleton)
      • Dùng Layer giống nhau giữa monster và vật cản để SRP gom vào chung batch
      • Việc biến SpriteRenderer thành Spine Animation rất đơn giản – tham khảo CreateSpineAnimForTextureExtensions.cs

      Skeleton vs Sprite Renderer

      🔴 Vòng tròn đỏ: Skeleton Animation
      🟢 Vòng tròn xanh: Sprite Renderer


      🧩 Sprite Renderer – Dùng chung Material & Atlas

      Khi vẫn dùng SpriteRenderer, cần dùng chung material và chung atlas để Unity nhóm các sprite lại thành 1 drawcall.

      Sprite Renderer Atlas Example


      🌿 GPU Instancing

      Dùng cho các object giống nhau:
      Ví dụ: cỏ, hiệu ứng vòng tròn tấn công, đá nhỏ, lá rơi, …
      → Giúp giảm drawcall mà vẫn giữ hiệu ứng động.


      🧭 Sắp xếp Layer hợp lý

      • Layer 1: Mặt đất, cây cỏ, rác, đá sỏi, các vật có thể bị đạp lên.
      • Layer 2: Monster, hero, effect, dog, base, obstacle – nơi các vật thể có thể che nhau.

      Layer Setup Example


      II. Optimize CPU

      🔄 Giảm đối tượng cần vẽ / tính toán

      Monster nằm ngoài camera chỉ cần cập nhật logic, không cần render.
      → Trong SkeletonAnimation, bật:
      Advanced → Update When Invisible → Only Event Timelines

      Update When Invisible Setting


      ⚡ Loại bỏ Collider / Rigidbody không cần thiết

      Dùng hệ thống va chạm logic tự tính thay cho vật lý thật:

      • Tính khoảng cách giữa tâm hero và monster.
      • Nếu nhỏ hơn bán kính kỹ năng → trong phạm vi tấn công.
        → Tham khảo: DetectCollideManager.cs.

      III. Optimize Addressables

      📦 Tổ chức theo Chapter

      Mỗi chapter là 1 group riêng, chọn Pack Together để Unity build thành 1 bundle duy nhất → gọn nhẹ, dễ load/unload.

      Addressable Group Setup


      🚫 Không bỏ Scene vào Addressable

      Scene luôn bị build dạng Pack Separately, dễ bị duplicate asset → tăng size bundle và memory.


      🧾 Config chỉ chứa data cơ bản

      • Chỉ nên chứa text, number, config JSON.
      • Không chứa sprite, texture, sound để tránh trùng atlas.
      • Nếu buộc phải có sprite → bỏ tích Include in Build trong atlas và dùng SpriteAtlasManager để load thủ công.

      Sprite Atlas Include Example

      Tham khảo: SpriteAtlasAddressableLoader.cs
      Tài liệu: Unity SpriteAtlasManager


      ♻️ Giải phóng tài nguyên đúng cách

      Mọi handle async của Addressables (LoadAssetAsync, InstantiateAsync, …)
      → Phải gọi Addressables.Release(handle) khi không dùng nữa.


      IV. Optimize Memory

      🚫 Không tạo object mới mỗi frame

      Không new string, new List, new Dictionary... trong Update → gây GC Alloc liên tục.
      → Dùng biến cache hoặc List.Clear() để tái sử dụng.

      Memory GC Example


      🧹 Dọn dẹp bộ nhớ

      Khi đổi scene, gọi:

      Addressables.ReleaseUnusedAssets();
      Resources.UnloadUnusedAssets();
      

      Có thể thêm GC.Collect() trong màn hình loading để thu hồi managed memory.


      🧱 Giảm phân mảnh bộ nhớ

      • Dùng List, Queue, Stack, Dictionary có capacity cố định.
      • Tính trước kích thước hợp lý ngay từ đầu để tránh reallocate.
      • Tham khảo code gốc của .NET List<T>:
        List.cs#L198
      • Dùng Object Pooling cho object tạo–hủy thường xuyên (đạn, hiệu ứng, popup...).

      V. Optimize Spine Animation

      • Gom tất cả monster cùng chapter vào 1 atlas duy nhất
        → ví dụ: Chapter_01_Monsters.atlas, Chapter_02_Monsters.atlas.
      • Nếu vùng sprite là hình lồi, cắt lồi để giảm vertices/triangle.
      • Bật Triangulate Low Detail hoặc giảm precision vùng mesh.
      • Tránh sprite có alpha phức tạp hoặc chi tiết biên thừa.
      • Giảm bone, attachment, slot không cần thiết.
      • Gộp nhiều attachment tĩnh thành 1 sprite duy nhất.
      • Xóa bone test, placeholder, slot không render.
      • Animation đơn giản (vd: idle) chỉ cần 2 keyframe đầu/cuối (Spine tự nội suy).
      • Xóa keyframe dư và animation không dùng runtime.

      VI. Optimize Texture

      • Dùng ASTC thay vì RGBA32 để giảm kích thước build và RAM.
      • Dùng ASTC 10×10 hoặc 12×12 nếu chất lượng hình ảnh vẫn ổn.
      • Gom sprite hợp lý vào atlas để giảm texture switch.

      VII. Optimize UIToolkit

      • Dùng usageHints:
        Giúp Unity xác định cách tối ưu layout và render cho UI element.
      • Giảm thay đổi transform:
        Không thay đổi position, rotation, scale thường xuyên — vì sẽ rebuild layout gây tốn CPU.

      VIII. Optimize Âm Thanh

      • Decompress On Load:
        Cho âm thanh phát liên tục (bắn, hit, bước chân).
      • Streaming:
        Cho âm thanh dài (nhạc nền, voice, cutscene).
      • Compress In Memory:
        Cho âm thanh ngắn, ít khi phát (click UI, hiệu ứng nhỏ).
      • Load In Background:
        Dùng cho các âm thanh không yêu cầu độ chính xác cao để không chặn luồng chính.

      IX. Optimize Script

      • Cache các giá trị dùng nhiều:

        • Animator.StringToHash (trigger animation).
        • LayerMask.GetMask, LayerMask.NameToLayer.
        • Camera.main (vì gọi lại sẽ FindGameObjectWithTag).
      • Tạo collection có capacity cụ thể:
        new List<int>(64) hoặc new Dictionary<string, int>(32) để tránh mở rộng mảng.

      • Dùng HashSet thay List:
        Nếu chỉ cần kiểm tra Contains, Add, Remove – tốc độ nhanh hơn nhiều.

      • Local Function:
        Đặt ở lớp ngoài cùng, truyền tham số rõ ràng để tránh GC capture closure.

      • Xoá các hàm Update() hoặc FixedUpdate() nếu không dùng đến

      posted in Developer Discussion
      C
      changx
    • [NATV] Spine Editor

      mục tiêu chính: mỗi chapter dùng 1 atlas do Spine Editor xuất, các bước thực hiện:
      1: tìm ra tên chung cho các con monster và các hiệu ứng của con monster đó, ví dụ như đạn, effect riêng liên quan đến con monster đó, bỏ vào thư mục chứa tên chung này, đưa các hình ảnh vào cho đúng
      2: effect chung của cả chapter là Star_Stunned để vào 1 thư mục riêng
      3: dùng Find And Replace trong SpineEditor để thực hiện đổi tên
      4: loại bỏ những tấm hình không được dùng đến, thực hiện đô
      5: export nhưng không cần pack atlas
      6: copy toàn bộ thư mục images ra 1 thư mục atlas_images, texture packer atlas_images này với scale size là (1 và 0.5)

      có thể tham khảo từ đây: \192.168.0.200\Shared\Artist\GAME - NATV\Chapter-Raidboss REFACTOR
      cho ví dụ:
      trong chapter raidboss:

      1. con Pertrified_Berserker có 1 hiệu ứng là Pertrified_Berserker FX, vì vậy tên chung của cả 2 file spine này là Pertrified_Berserker, tạo 1 thư mục images/Pertrified_Berserker trong cả Pertrified_Berserker và Pertrified_Berserker FX
        5086ca06-0bc5-4fab-a070-45a58e8a4cfe-image.png
      2. tạo 1 thư mục là images/Star_Stunned
        454fa63c-e2d5-431c-8163-98885a6f3980-image.png

      Find: (.*)
      Replace: Pertrified_Berserker/$1
      các option còn lại chọn giống trong hình dưới
      3a2d4bbf-123c-4a84-ab82-c28b3d2af19d-image.png
      4. tìm xem các hình không được dùng đến thì thực hiện xoá
      5. export với setting sau:
      14dec5e4-e069-4438-a3f6-19dd26035035-image.png
      6: tạo 1 folder là Chapter_Raidboss_atlas, tạo thêm 1 images: copy tất cả thư mục images từ tất cả các con trên và bỏ vào trong này, sau đó dùng Spine Editor chọn chức năng TexturePacker: Input folder: là thư mục vừa rồi
      6618ba2b-c0a7-47c4-abf8-b2cfdf5396af-image.png
      Settings giống như sau:
      b3ac9e86-0778-484a-8711-a07783b346d8-image.png

      posted in Developer Discussion
      C
      changx
    • RE: sử dụng ACTk unity cho hiệu quả
      // cả 2 cái initValue1 và initValue2 có 5 và 3 đều dễ bị chỉnh sửa, thay thành dạng GlobalConstance hoặc static readonly ObscuredInt INIT_VALUE_1= 5;
      
      public class ConfigItem {
          public ObscuredInt initValue1 = 5;
      
          public ObscuredInt initValue2;
      
          public ConfigItem () {
              initValue2 = 3;
          } 
      }
      
      
      posted in Developer Discussion
      C
      changx
    • sử dụng ACTk unity cho hiệu quả

      đối với property

      // không an toàn vì khi build ra nó sẽ thành public int get_coin() { // chỗ này quá dễ để cheat chỉnh sửa }
      public int coin => s_coin;
      private ObscuredInt s_coin;
      
      // chỗ này cũng như property coin bên trên, không sử dụng
      public int getCoin() { return  s_coin; }
      

      đổi lại thành

      // khó để return 1 ObscuredInt hơn trong memory
          public ObscuredInt coin => s_coin;
          private ObscuredInt s_coin;
      
      

      trong hàm

      void ChangeGemToCoin() {
          // 2 cái gemCost và coinRecv  không an toàn
          ObscuredInt gemCost = 10;
          ObscuredInt coinRecv = 100;
      
          // vd logic để thay đổi tiền 
          applicationUser.gem -= gemCost;
          applicationUser.coin += coinRecv;
      }
      

      đổi lại thành

      // cái này này đảm bảo việc GEM_COST và COIN_RECV phải được tạo ra khi vừa start chương trình
      public class GlobalConstance {
          public static readonly ObscuredInt GEM_COST = 10;
          public static readonly ObscuredInt COIN_RECV = 100;
      }
      
      void ChangeGemToCoin() {
          
          ObscuredInt gemCost = GlobalConstance.GEM_COST;
          ObscuredInt coinRecv = GlobalConstance.COIN_RECV;
      
          // vd logic để thay đổi tiền 
          applicationUser.gem -= gemCost;
          applicationUser.coin += coinRecv;
      }
      
      posted in Developer Discussion
      C
      changx
    • Lỗ hỏng bảo mật của ACTk Unity

      xem thử 1 biến như ObscuredLong, đoạn hàm Encrypt và Decrypt được viết như sau

      public static long Encrypt(long value, long key)
      {
      	unchecked
      	{
      		return (value ^ key) + key;
      	}
      }
      
      public static long Decrypt(long value, long key)
      {
      	unchecked
      	{
      		return (value - key) ^ key;
      	}
      }
      

      value là giá trị gốc chưa bị che, nếu key = 0 thì (value ^ key) + key sẽ luôn = value; đoạn này được sử dụng trong ObscuredLong như sau:

      currentCryptoKey = GeneratePrivateKey();
      hiddenValue = Encrypt(value, currentCryptoKey);
      

      nếu vậy mục tiêu của mình chỉ cần dùng CheatEngine chỉnh sửa để GeneratePrivateKey() luôn return 0; vậy là hiddenValue sẽ lộ ra và lúc này chỉnh sửa bất kỳ giá trị nào dùng ObscuredLong dễ dàng

      posted in Developer Discussion
      C
      changx
    • RE: Lưu

      @changx
      Việc không localization khi thực hiện NEWS và MAIL BOX tính năng mới trong NATV có thể châm trước là vì game chỉ hỗ trợ tiếng anh nên không thực hiện localization

      Tuy nhiên việc scrollrect hoạt động không chính xác tại MAIL BOX đã được yêu cầu để fix thì lại bỏ qua scrollrect chạy trên NEWS là cần xem lại về thái độ không cẩn thận khi thực hiện task, rõ ràng 2 cái này là Lưu là người làm UI cho nó thì khi biết được cần fix scrollrect bên MAIL BOX thì tại sao không fix luôn bên NEWS, thái độ thiếu chủ động trong công việc, cần phải chủ động và linh hoạt hơn

      posted in Adminstrator
      C
      changx
    • RE: Lưu

      @changx

      hệ thống trang bị vật phẩm có sáng tạo và giải quyết tốt việc có thể mở rộng sau này, đây là điểm cộng

      posted in Adminstrator
      C
      changx
    • Lưu

      Nguyễn Hoàng Lưu

      posted in Adminstrator
      C
      changx