Blog | 新的开始

迁移博客

我是从18年开始写一些东西,先写在看云笔记上,后面东西越来越多。写出来的东西比较零散.

20年下半年入职新公司,开始在csdn上写博客,今年我准备尝试使用个人博客,hugo和gitPage结合部署静态博客,csdn上没怎么更新.

……

阅读全文

Skynet源码赏析四 | 消息调度

服务间消息流转

发送消息

数据结构message_queue *q是次级消息队列,每个服务都有与之绑定的唯一一个次级消息队列。当我们在lua层,调用skynet.send(...), 或者调用skynet.call(...)函数发送消息,其实调用的都是c.send(...),实际上调用的是c接口:

……

阅读全文

Skynet源码赏析三 | 服务启动

skynet启动一个C服务

查看怎么启动C服务的最好的办法是打断点,看源码。

启动logger日志服务

我拿日志服务来举例子,怎么启动日志服务的呢?

  1. 传参数name = "logger", param = nullstruct skynet_context *ctx = skynet_context_new(config->logservice, config->logger);;
  2. 从modules服务模块中取出名字为 logger的服务, struct skynet_module * result = _query(name);;
  3. 如果找不到则从cpath目录中找对应的.so文件,打开服务,并且存储到modules模块中。使用的函数是static void * _try_open(struct modules *m, const char * name);
  4. 创建服务实例m->create(),放到上下文skynet_contextinst中;
  5. skynet_context放到skynet_context list中, skynet_handle_register(ctx);;
  6. 创建logger服务对应的次级消息队列struct message_queue *queue,并且把消息队列push到全局消息队列中skynet_mq_create(ctx->handle);skynet_globalmq_push(queue);;
  7. 服务实例初始化m->init(),int r = skynet_module_instance_init(mod, inst, ctx, param);

总结下来,启动一个服务的过程就是,1.获取服务;2.创建服务实例;3.创建服务对应的上下文,并且把上下文放到skynet_context list管理模块中;4.绑定次级消息队列与对应的服务;5.服务初始化; 这五步过程。

……

阅读全文

Skynet源码赏析二 | 基础数据结构

module管理模块

我们所写的C服务编译成.so文件后放在cpath变量路径下,程序会加载路径cpath = root.."cservice/?.so"下的.so文件,通过static void * _try_open(struct modules *m, const char * name)函数第一次打开,然后被加载到全局变量static struct modules * M中。

……

阅读全文

Skynet源码赏析一 | 启动初始化的过程

入口文件

skynet_main.c

加载配置

struct skynet_config config;
config.thread =  optint("thread",8);
config.module_path = optstring("cpath","./cservice/?.so");
config.harbor = optint("harbor", 1);
config.bootstrap = optstring("bootstrap","snlua bootstrap");
config.daemon = optstring("daemon", NULL);
config.logger = optstring("logger", NULL);
config.logservice = optstring("logservice", "logger");
config.profile = optboolean("profile", 1);

从上述代码可以看到,配置都已经加载到变量struct skynet_config config;中了。

初始化

  1. 初始化skynet_context管理模块, skynet_handle_init(config->harbor);;
  2. 初始化static struct global_queue *Q消息队列, skynet_mq_init();;
  3. 初始化static struct modules * M管理模块, skynet_module_init(config->module_path);;
  4. 初始化定时器, skynet_timer_init();;

启动C服务

  1. 启动logger日志服务, struct skynet_context *ctx = skynet_context_new(config->logservice, config->logger);;
  2. 启动 snlua服务, ``;
  3. 通过snlua服务启动boostrap服务, bootstrap(ctx, config->bootstrap);;
  4. 启动线程:
  • 监听线程,检测线程是否阻塞。 create_thread(&pid[0], thread_monitor, m);;
  • 启动定时器线程。create_thread(&pid[1], thread_timer, m);;
  • 启动socket线程。create_thread(&pid[2], thread_socket, m);
  • 启动工作线程,用于lua服务消息的调度。create_thread(&pid[i+3], thread_worker, &wp[i]);;

启动lua服务

默认启动的lua服务,在boostrap.lua文件中可以看到都是通过snlua服务启动的。

……

阅读全文

FPS游戏 | 实现移动功能

三种实现FPS Controller的区别

  1. Transform Translate 允许移动物理,但无物理碰撞
  2. Rigid body + Capsule Collider 符合物理学 不会鬼穿墙 无法滞空运动 可与Physics Object 交互
  3. Charactor Controller 不会鬼穿墙 提供的API相对多 无法与Physic objects互动 可以滞空运动(太空人) 提供多种运动效果例如 slopes steps 等

Rigid body + Capsule Collider

控制摄像头旋转 FPMouseLook.cs 跟main camera 绑定

……

阅读全文

免费Music

介绍一个可以免费听音乐的方法

环境

  • docker
  • mac

安装

$ docker run -d -p 264:264 -p 9000:9000 -v $dir_name:/var/www/html/cache --name music oldiy/music-player-docker

$dir_name 是 你自己宿主机的目录。可以自定义

访问:127.0.0.1:264

就可以放心使用, 同事推荐的,贼好用。

……

阅读全文

Unity3D | Transform类

Transform类

在unity中,把transform类理解为,transform类是在每个对象生成时自动附加的一个类。在Unity的视图中,点击Hierarchy中的对象,就可以在Inspector中可以看到存在Transform的组件。

……

阅读全文

Vim | 切换模式/输入法

vim 在退出输入模式的时候切换为原来的输入法

在敲代码的时候使用我们使用的英文,当遇到问题,我们需要搜索引擎的时候需要中文输入法,这个时候,自动切换输入法可以帮助我们节省手动切换输入法的时间。

跟编辑器结合,主要是两种编辑器,一个是 idea 一个是 vscode

……

阅读全文