文档章节

Unity定时器堆栈显示

梦想游戏人
 梦想游戏人
发布于 2017/09/04 16:36
字数 510
阅读 10
收藏 0
点赞 0
评论 0

一般定时器是一个匿名函数,callback,在函数执行错误的话,很难查找到错误信息。

在这里可以利用添加定时器的时候 对调用栈进行一个快照,当发生错误时输出即可,这样调试起来方便多了。

 

AddTimer中栈 信息的一个快照为string 作为Timer对象的成员,release发行时可以去掉这种辅助机制

/*
* Author:  caoshanshan
* Email:   me@dreamyouxi.com
code copy from https://git.oschina.net/dreamyouxi/XYGame;
 */
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using ExtBase;

public sealed class TimerQueue : Singleton<TimerQueue>
{

    /// <summary>
    /// 添加一个真实时间定时器,返回函数调用即可 打断定时任务
    /// </summary>
    /// <param name="time_delay"></param>
    /// <param name="cb"></param>
    /// <param name="repeat_times">  <0 will be run forever</param>
    public VoidFuncVoid AddTimer(float time_delay, VoidFuncNN cb, int repeat_times = 1, params object[] objs)
    {
        return this.AddTimer(time_delay, () => { cb(objs); }, repeat_times);
    }
    /// <summary>
    /// 添加一个真实时间定时器,返回函数调用即可 打断定时任务
    /// </summary>
    /// <param name="time_delay"></param>
    /// <param name="cb"></param>
    /// <param name="repeat_times">  <0 will be run forever</param>
    public VoidFuncVoid AddTimer(float time_delay, VoidFuncVoid cb, int repeat_times = 1)
    {
        if (repeat_times == 0) return null;// () => { };
        Timer time = new Timer();
        time.delay = time_delay;
        time.cb = cb;
        time.repeat_times = repeat_times;
        //记录定时器添加的时候的快照栈信息,以 提供错误时 更多调试信息
        System.Diagnostics.StackTrace st = new System.Diagnostics.StackTrace(true);

        string ss = "\n";
        for (int i = 0; i < st.FrameCount; i++)
        {
            var f = st.GetFrame(i);
            string name = f.GetFileName();
            if (name.Length > Application.dataPath.Length)
            {
                name = name.Substring(Application.dataPath.Length, name.Length - Application.dataPath.Length);
            }
            ss += "   " + f.GetMethod().ToString() + " at " + name + " (" + f.GetFileLineNumber() + ") \n";
        }
        time.stackInfo = ss;
        time.Init();
        list.Add(time);
        return () =>
        {
            if (time != null && this.list.Contains(time))
                time.SetInValid();
        };
    }

    /// <summary>
    /// unity engine tick
    /// </summary>
    public void Tick()
    {
        this.Tick(ref list);
    }
    private void Tick(ref List<TimerBase> list)
    {
        if (list.Count < 1)
            return;

        for (int i = 0; i < list.Count; i++)
        {
            if (list[i] == null)
                continue;

            TimerBase timer = list[i] as TimerBase;
            timer.Tick();
        }

        for (int i = 0; i < list.Count; )
        {
            TimerBase b = list[i] as TimerBase;
            if (b.IsInValid())
            {
                list.Remove(b);
            }
            else
            {
                ++i;
            }
        }
    }
    public void Clear()
    {
        this.list_ms.Clear();
        this.list.Clear();
    }
    List<TimerBase> list_ms = new List<TimerBase>();
    List<TimerBase> list = new List<TimerBase>();

}


class TimerBase : GAObject
{
    public string stackInfo = "";
    public virtual void Tick()
    {

    }

    public VoidFuncVoid cb = null;
    public int repeat_times = 1;
    protected int repeat_times_current = 0;
}

sealed class Timer : TimerBase
{
    public override void Tick()
    {
        if (this.IsInValid()) return;

        if (current < delay)
        {
            current += Time.deltaTime;
            return;
        }
        if (cb != null)
        {
            try
            {
                cb();
            }
            catch (System.Exception e)
            {
                Debug.LogError(e.Message);
                Debug.LogError("add timer stackTrace:" + this.stackInfo);
                Debug.LogError("call stackTrace:" + e.StackTrace);
            }
            cb = null;
        }
        current = 0.0f;
        if (++repeat_times_current >= repeat_times && repeat_times >= 0)
        {
            this.SetInValid();
        }
    }

    public override bool Init()
    {
        return true;
    }
    float current = 0.0f;
    public float delay = 0.0f;

}

 

© 著作权归作者所有

共有 人打赏支持
梦想游戏人
粉丝 34
博文 402
码字总数 115594
作品 0
成都
学习Mono与Unity3D关系的笔记

Xamarin公司开发的跨平台 .NET运行环境,是.NET框架的另一种实现。区别在于,它可以跨平台。(Unity的跨平台特性依赖于Mono) Mono的组成。 1.C#编译器。 最新的Momo版本(5.0+)c#编译器完全...

lishengxu159 ⋅ 05/05 ⋅ 0

Unity-UnityScript转换C#工具(js转c#)

如何使用 首先,从https://github.com/Unity-Technologies/unityscript2csharp/releases下载工具。 运行转换工具之前: 备份您的项目 请记住,如果您的UnityScripts将#pragma严格应用于它们,...

qq_21153225 ⋅ 05/09 ⋅ 0

Unity2018新功能抢鲜 | Package Manager

本文首发于“洪流学堂”微信公众号。 洪流学堂,让你学Unity快人几步 一个包是一个容器,它可以包含各种资源的组合:shader、纹理、插件、图标、脚本等,可以增强项目的各个部分。相对于Ass...

zhenghongzhi6 ⋅ 04/21 ⋅ 0

Unity 3D 开发《王者荣耀》:Hello World

Unity 安装 Unity 官方网站:https://unity3d.com 点击右上角的 获取Unity 系统要求 OS: Windows 7 SP1+, 8, 10, 64-bit versions only; Mac OS X 10.9+. GPU:有DX9(着色器模型2.0)功能的...

iOSDevLog ⋅ 05/22 ⋅ 0

Unity网页数据交互基本原理

1. u3d是一个3D游戏引擎由于和编辑器集成在一起 所以也可以理解为一个制作/开发平台 2. u3d使用javascript C#作为核心脚本语言 来驱动整个游戏引擎 3. 平台可以发布为Exe执行文件或者打包为供...

qq_30279553 ⋅ 04/22 ⋅ 0

【AR】在Unity中开始使用Vuforia(1)

原 目录 在Unity中开始使用Vuforia Vuforia在统一 关于Vuforia 安装Vuforia 创建一个新的Unity项目 Vuforia游戏对象 在您的项目中激活Vuforia 访问Unity中的Vuforia功能 将目标添加到您的场景...

lichong951 ⋅ 06/11 ⋅ 0

UnityShader源码2017---学习笔记与自我拓展006

源自CubeBlend 首先映入眼帘的是 稍微解释一下[NoScaleOffset]吧,就是在material的面板上没有tilling和offset控制部分的GUI显示。 然后我看到了 这个应该是unity声明的吧,比如想MainTexST...

u012871784 ⋅ 05/29 ⋅ 0

Unity3D利用Webservice读取数据库

相信大家从事Unity3D开发的,无论是做单机的还是做网游的,特别是稍微大点的项目,都会用到数据库,但是网络上关于Unity3D如何连接数据库的教程少之甚少,搜来搜去无非是那篇Unity3D如何连接...

qq_30279553 ⋅ 04/22 ⋅ 0

Unity2018新功能抢鲜 | 粒子系统改进

本文首发于“洪流学堂”微信公众号。 洪流学堂,让你学Unity快人几步 Unity2018.1中对粒子系统进行了重大改进,包括功能、性能很多方面,快来看看吧! GPU网格实例化 粒子系统现在支持GPU实例...

zhenghongzhi6 ⋅ 04/17 ⋅ 0

Unity3D - 图片资源导入的一些基础知识

在上一篇文章里 Unity3D - 你导入的资源,并不是Unity使用的资源 介绍过,Unity使用的资源是你无法直接操作的,那么对于图片资源,我们应该如何去处理和优化工作流程呢? 图片资源的分类 在U...

qq_17758883 ⋅ 04/11 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Spring发展历程总结

转自与 https://www.cnblogs.com/RunForLove/p/4641672.html 目前很多公司的架构,从Struts2迁移到了SpringMVC。你有想过为什么不使用Servlet+JSP来构建Java web项目,而是采用SpringMVC呢?...

onedotdot ⋅ 46分钟前 ⋅ 0

Python模块/包/库安装(6种方法)

Python模块/包/库安装(6种方法) 冰颖机器人 2016-11-29 21:33:26 一、方法1: 单文件模块 直接把文件拷贝到 $python_dir/Lib 二、方法2: 多文件模块,带setup.py 下载模块包(压缩文件zip...

cswangyx ⋅ 今天 ⋅ 0

零基础学习大数据人工智能,学习路线篇!系统规划大数据之路?

大数据处理技术怎么学习呢?首先我们要学习Python语言和Linux操作系统,这两个是学习大数据的基础,学习的顺序不分前后。 Python:Python 的排名从去年开始就借助人工智能持续上升,现在它已经...

董黎明 ⋅ 今天 ⋅ 0

openJdk和sun jdk的区别

使用过LINUX的人都应该知道,在大多数LINUX发行版本里,内置或者通过软件源安装JDK的话,都是安装的OpenJDK, 那么到底什么是OpenJDK,它与SUN JDK有什么关系和区别呢? 历史上的原因是,Ope...

jason_kiss ⋅ 今天 ⋅ 0

梳理

Redux 是 JavaScript 状态容器,提供可预测化的状态管理。 它是JS的状态容器,是一种解决问题的方式,所以即可以用于 react 也可以用于 vue。 需要理解其思想及实现方式。 应用中所有的 stat...

分秒 ⋅ 今天 ⋅ 0

Java 后台判断是否为ajax请求

/** * 是否是Ajax请求 * @param request * @return */public static boolean isAjax(ServletRequest request){return "XMLHttpRequest".equalsIgnoreCase(((HttpServletReques......

JavaSon712 ⋅ 今天 ⋅ 0

Redis 单线程 为何却需要事务处理并发问题

Redis是单线程处理,也就是命令会顺序执行。那么为什么会存在并发问题呢? 个人理解是,虽然redis是单线程,但是可以同时有多个客户端访问,每个客户端会有 一个线程。客户端访问之间存在竞争...

码代码的小司机 ⋅ 今天 ⋅ 0

到底会改名吗?微软GVFS 改名之争

微软去年透露了 Git Virtual File System(GVFS)项目,GVFS 是 Git 版本控制系统的一个开源插件,允许 Git 处理 TB 规模的代码库,比如 270 GB 的 Windows 代码库。该项目公布之初就引发了争...

linux-tao ⋅ 今天 ⋅ 0

笔试题之Java基础部分【简】【二】

1.静态变量和实例变量的区别 在语法定义上的区别:静态变量前要加static关键字,而实例变量前则不加。在程序运行时的区别:实例变量属于某个对象的属性,必须创建了实例对象,其中的实例变...

anlve ⋅ 今天 ⋅ 0

Lombok简单介绍及使用

官网 通过简单注解来精简代码达到消除冗长代码的目的 优点 提高编程效率 使代码更简洁 消除冗长代码 避免修改字段名字时忘记修改方法名 4.idea中安装lombnok pom.xml引入 <dependency> <grou...

to_ln ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部