devNotes 7-09-16 exercise fluid pathways

fghjhfgj7

 

public float updateInterval = 0.5F;
 private float accum = 0; // FPS accumulated over the interval
 private int frames = 0; // Frames drawn over the interval
 private float timeleft; // Left time for current interval
 private string fpsText;
 private GameObject[] AllObjects;
 private int DrawCalls;
 void CalculateFPS()
 {
     timeleft -= Time.deltaTime;
     accum += Time.timeScale / Time.deltaTime;
     ++frames;
     // Interval ended - update GUI text and start new interval
     if (timeleft <= 0.0)
     {
         // display two fractional digits (f2 format)
         float fps = accum / frames;
         string format = System.String.Format("{0:F2} FPS", fps);
         fpsText = format;
         timeleft = updateInterval;
         accum = 0.0F;
         frames = 0;
     }
 }
 void Draw_DrawCalls()
 {
     foreach (GameObject g in AllObjects)
     {
         if (g.renderer && g.renderer.isVisible)
         {
             DrawCalls++;
         }
     }
 }
 void Start () {
     timeleft = updateInterval;
     AllObjects = (GameObject[])GameObject.FindObjectsOfType(typeof(GameObject)) ;
     
 }
 
 // Update is called once per frame
 void Update () {
     CalculateFPS();
     Draw_DrawCalls();
 }
 void OnGUI() {
     GUI.Label(new Rect(0.0f, 0.0f, 100.0f, 25.0f), fpsText);
     GUI.Label(new Rect(0.0f, 50.0f, 200.0f, 25.0f), "Total Draw Calls : "+ DrawCalls.ToString());
 }

 

  1. Macrotexture everything. Macrotexturing is the process of using the smallest number of textures possible in the scene.  The levels in Wind-up Knight 2 all fit into 4 1024×1024 textures.  This is fast for a number of reasons, but one of the main benefits is that it allows us to batch all of the visible geometry using the same texture up into a single VBO and send it to the GPU all at once.  Unity does a good job of this automatically with its dynamic batching option.  Macrotexturing is hard, and it requires an artist with a lot of foresight, serious modeling skills, and a willingness to rework things to accommodate changes in the textures.  But it’s absolutely worth it.
  2. Batch everything. In addition to dynamic batching based on material, we also try to combine meshes that we know won’t move.  Unity calls this static batching, and it’s great for level geometry or other mesh elements that never move.  Rather than making our scene static in the editor, we usually mark all objects that can be made static with a particular layer, then use Unity’s StaticBatchingUtility to combine static meshes at level load time.  This increases load time a bit but dramatically reduces the size of our game binary.
  3. Control draw order.  On a PC, you probably draw your scene from back to front, starting with a skybox and ending with the closest bits to the camera, followed by a pass for transparent objects or other items needing blending.   On mobile, however, this incurs an unacceptable amount of overdraw.  So we try to draw as much as possible front-to-back, with the skybox and other large objects that can potentially touch a large number of pixels on the screen drawn as the last step before transparent objects.  Rejecting a pixel with a depth test is much faster than filling that pixel unnecessarily several times, so front-to-back for opaque geometry is a big win.
  4. Watch out for transparency.  Transparency is, by definition, the process of filling a pixel more than one time.  Therefore, on mobile, it’s very expensive to have large objects that covers part of the screen in semi-transparent pixels.  Even worse is layers of transparency.  You can get away with small small regions of the screen, but once a transparent object starts to touch a lot of pixels, the frame time cost will be high.  We try to organize our transparent objects such that there is minimal overlap and that they take up as few pixels on the screen as possible.
  5. Design to scale.  It’s hard to find a perfect balance between “looks good” and “runs fast” on mobile, mostly because there’s such a wide spectrum of power out there.  A modern device like the Nexus 5 or iPhone 5 can push scenes that are orders of magnitude more complex than their predecessors from three or four years ago.  Therefore, we design our scene such that we can tone down the graphics quality in exchange for performance on lower-end displays.  We drop the highest texture mip on displays smaller than iPhone 4 resolution.  We down-res the size of the final render target by 15% or 25% on very slow devices. We dynamically detect framerate changes and switch between pixel lights and spherical harmonics on the fly.  These are easy to do if you are thinking about them early.

gj,jhgj,j

fghjfghjg

Also note that the Oculus Mobile SDK introduces an API for throttling the CPU and GPU to control heat and battery drain (see OVRModeParams.cs for sample usage). These methods allow you to choose whether the CPU or GPU is more important for your particular scene. For example, if you are bound on draw call submission, clocking the CPU up (and the GPU down) might improve overall frame rate. If you neglect to set these values, your application will be throttled down significantly, so take time to experiment with them.

 

https://developer.android.com/studio/profile/monitor.html

http://argos.vu/squeezing-performance-out-of-your-unity-gear-vr-game/


using UnityEngine;
using System.Collections;
using UnityEditor;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System;
using System.IO;

public class LogCatWindow : EditorWindow
{
    StreamWriter sWrite;
    // How many log entries to store in memory. Keep it low for better performance.
    private const int memoryLimit = 2000;

    // How many log entries to show in unity3D editor. Keep it low for better performance.
    private const int showLimit = 200;

    // Filters
    private bool prefilterOnlyUnity = true;
    private bool filterOnlyError = false;
    private bool filterOnlyWarning = false;
    private bool filterOnlyDebug = false;
    private bool filterOnlyInfo = false;
    private bool filterOnlyVerbose = false;
    private string filterByString = String.Empty;

    // Android adb logcat process
    private Process logCatProcess;

    // Log entries
    private List<LogCatLog> logsList = new List<LogCatLog>();
    private List<LogCatLog> filteredList = new List<LogCatLog>(memoryLimit);

    // Filtered GUI list scroll position
    private Vector2 scrollPosition = new Vector2(0, 0);

    // Add menu item named "LogCat" to the Window menu
    [MenuItem("Window/LogCat - Android Logger")]
    public static void ShowWindow()
    {
        // Show existing window instance. If one doesn't exist, make one.
        EditorWindow.GetWindow(typeof(LogCatWindow), false, "Logcat");
    }

    void Update()
    {
        if (logsList.Count == 0)
            return;

        lock (logsList)
        {
            // Filter
            filteredList = logsList.Where(log => (filterByString.Length <= 2 || log.Message.ToLower().Contains(filterByString.ToLower())) &&
                                          ((!filterOnlyError && !filterOnlyWarning && !filterOnlyDebug && !filterOnlyInfo && !filterOnlyVerbose)
             || filterOnlyError && log.Type == 'E'
             || filterOnlyWarning && log.Type == 'W'
             || filterOnlyDebug && log.Type == 'D'
             || filterOnlyInfo && log.Type == 'I'
             || filterOnlyVerbose && log.Type == 'V')).ToList();
        }
    }

    void OnGUI()
    {
        GUILayout.BeginHorizontal();

        // Enable pre-filter if process is not started
        GUI.enabled = logCatProcess == null;
        prefilterOnlyUnity = GUILayout.Toggle(prefilterOnlyUnity, "Only Unity", "Button", GUILayout.Width(80));

        // Enable button if process is not started
        GUI.enabled = logCatProcess == null;
        if (GUILayout.Button("Start", GUILayout.Width(60)))
        {
            // Start `adb logcat -c` to clear the log buffer
            ProcessStartInfo clearProcessInfo = new ProcessStartInfo();
            clearProcessInfo.WindowStyle = ProcessWindowStyle.Hidden;
            clearProcessInfo.CreateNoWindow = true;
            clearProcessInfo.UseShellExecute = false;
            clearProcessInfo.FileName = EditorPrefs.GetString("AndroidSdkRoot") + "/platform-tools/adb";
            clearProcessInfo.Arguments = @"logcat -c";
            Process.Start(clearProcessInfo);

            // Start `adb logcat` (with additional optional arguments) process for filtering
            ProcessStartInfo logProcessInfo = new ProcessStartInfo();
            logProcessInfo.CreateNoWindow = true;
            logProcessInfo.UseShellExecute = false;
            logProcessInfo.RedirectStandardOutput = true;
            logProcessInfo.RedirectStandardError = true;
            logProcessInfo.FileName = EditorPrefs.GetString("AndroidSdkRoot") + "/platform-tools/adb";
            logProcessInfo.WindowStyle = ProcessWindowStyle.Hidden;

            // Add additional -s argument for filtering by Unity tag.
            logProcessInfo.Arguments = "logcat" + (prefilterOnlyUnity ? " -s  \"Unity\"" : "");

            logCatProcess = Process.Start(logProcessInfo);

            logCatProcess.ErrorDataReceived += (sender, errorLine) =>
            {
                if (errorLine.Data != null && errorLine.Data.Length > 2)
                    AddLog(new LogCatLog(errorLine.Data));
            };
            logCatProcess.OutputDataReceived += (sender, outputLine) =>
            {
                if (outputLine.Data != null && outputLine.Data.Length > 2)
                    AddLog(new LogCatLog(outputLine.Data));
            };
            logCatProcess.BeginErrorReadLine();
            logCatProcess.BeginOutputReadLine();
        }

        // Disable button if process is already started
        GUI.enabled = logCatProcess != null;
        if (GUILayout.Button("Stop", GUILayout.Width(60)))
        {
            try
            {
                logCatProcess.Kill();
            }
            catch (InvalidOperationException ex)
            {
                // Just ignore it.
            }
            finally
            {
                logCatProcess = null;

            }
        }

        GUI.enabled = true;
        if (GUILayout.Button("Clear", GUILayout.Width(60)))
        {
            lock (logsList)
            {
                logsList.Clear();
                filteredList.Clear();
            }
        }
        if (GUILayout.Button("Save", GUILayout.Width(60)))
        {
            sWrite = new StreamWriter("LogCat_"+ DateTime.Now.ToString("H_mm_ss") + ".txt");
            for(int i = 0; i< logsList.Count; i++)
            {
                sWrite.WriteLine(logsList[i].Type  + " - " + logsList[i].Message);
            }
            sWrite.Close();
        }

        GUILayout.Label(filteredList.Count + " matching logs", GUILayout.Height(20));

        // Create filters
        filterByString = GUILayout.TextField(filterByString, GUILayout.Height(20));
        GUI.color = new Color(0.75f, 0.5f, 0.5f, 1f);
        filterOnlyError = GUILayout.Toggle(filterOnlyError, "Error", "Button", GUILayout.Width(80));
        GUI.color = new Color(0.95f, 0.95f, 0.3f, 1f);
        filterOnlyWarning = GUILayout.Toggle(filterOnlyWarning, "Warning", "Button", GUILayout.Width(80));
        GUI.color = new Color(0.5f, 0.5f, 0.75f, 1f);
        filterOnlyDebug = GUILayout.Toggle(filterOnlyDebug, "Debug", "Button", GUILayout.Width(80));
        GUI.color = new Color(0.5f, 0.75f, 0.5f, 1f);
        filterOnlyInfo = GUILayout.Toggle(filterOnlyInfo, "Info", "Button", GUILayout.Width(80));
        GUI.color = Color.white;
        filterOnlyVerbose = GUILayout.Toggle(filterOnlyVerbose, "Verbose", "Button", GUILayout.Width(80));

        GUILayout.EndHorizontal();

        GUIStyle lineStyle = new GUIStyle();
        lineStyle.normal.background = MakeTexture(600, 1, new Color(1.0f, 1.0f, 1.0f, 0.1f));

        scrollPosition = GUILayout.BeginScrollView(scrollPosition, GUILayout.Height(Screen.height - 45));

        // Show only top `showingLimit` log entries
        int fromIndex = filteredList.Count - showLimit;
        if (fromIndex < 0)
            fromIndex = 0;

        for (int i = fromIndex; i < filteredList.Count; i++)
        {
            LogCatLog log = filteredList[i];
            GUI.backgroundColor = log.GetBgColor();
            GUILayout.BeginHorizontal(lineStyle);
            GUILayout.Label(log.Type + " | " + log.Message);
            GUILayout.EndHorizontal();
        }
        GUILayout.EndScrollView();
    }

    private Texture2D MakeTexture(int width, int height, Color col)
    {
        Color[] pix = new Color[width * height];

        for (int i = 0; i < pix.Length; i++)
            pix[i] = col;

        Texture2D result = new Texture2D(width, height);
        result.SetPixels(pix);
        result.Apply();

        return result;
    }

    private void AddLog(LogCatLog log)
    {
        lock (logsList)
        {
            if (logsList.Count > memoryLimit + 1)
                logsList.RemoveRange(0, logsList.Count - memoryLimit + 1);

            logsList.Add(log);
        }
    }

    private class LogCatLog
    {
        public LogCatLog(string data)
        {
            // First char indicates error type:
            // W - warning
            // E - error
            // D - debug
            // I - info
            // V - verbose
            int count = 0;
            bool FindType = false;
            foreach (var c in data)
            {
                if (c == 'W' || c == 'I' || c == 'E' || c == 'D' || c == 'V')
                {
                    Type = c;
                    break;
                }
            }

            Message = data;
            //CreationDate = DateTime.Now.ToString("H:mm:ss");
        }

        public string CreationDate
        {
            get;
            set;
        }

        public char Type
        {
            get;
            set;
        }

        public string Message
        {
            get;
            set;
        }

        public Color GetBgColor()
        {
            switch (Type)
            {
                case 'W':
                    return Color.yellow;

                case 'I':
                    return Color.green;

                case 'E':
                    return Color.red;

                case 'D':
                    return Color.blue;

                case 'V':
                default:
                    return Color.grey;
            }
        }
    }
}