为什么我的Erlang服务器不睡眠?

为什么我的Erlang服务器不睡眠?,erlang,otp,Erlang,Otp,我已经编写了一个Erlang OTP服务器,它在我的游戏中处理一个子弹。当我开始这个过程时,我希望它开始一个递归函数,每个请求都有一些延迟。我的问题是,这种拖延似乎没有发生。我认为根本不需要“转发”的句柄信息。。。我做错了什么 一旦服务器启动,所有中继器字符串都会立即打印在终端上 这是从另一台服务器发出的启动项目符号的调用: {ok,BullPid} = gen_server:start('bullet', [self(), Type, Direction, Pos, ClientMaster]

我已经编写了一个Erlang OTP服务器,它在我的游戏中处理一个子弹。当我开始这个过程时,我希望它开始一个递归函数,每个请求都有一些延迟。我的问题是,这种拖延似乎没有发生。我认为根本不需要“转发”的句柄信息。。。我做错了什么

一旦服务器启动,所有中继器字符串都会立即打印在终端上

这是从另一台服务器发出的启动项目符号的调用:

{ok,BullPid} = gen_server:start('bullet', [self(), Type, Direction, Pos, ClientMaster], []),
这是服务器:

-module('bullet').

-export([init/1, handle_info/2, handle_cast/2, terminate/2]).

repeater(0) ->
    exit(normal);
repeater(Counter) ->
    io:fwrite("REPEATER\n"),
    erlang:send_after(100, self(), forward),
    repeater(Counter-1).

init([Client, _Type, Direction, StartPos, ClientMaster]) ->
    gen_server:cast(self(), startRepeater),
    io:fwrite("BULLET INITED!!"),
    Size = {10, 10},
    {ok, {Direction, {StartPos, Size, Client}, ClientMaster}}.

handle_cast(startRepeater, {Direction, Bullet, ClientMaster}) ->
    repeater(200),
    {noreply, {Direction, Bullet, ClientMaster}}.

handle_info(forward, {Direction, {Pos, Size, Client}, ClientMaster}) ->
    io:fwrite("forward"),
    Hit = gen_server:call(ClientMaster, {bullet, {Pos, Size, Client}, Direction}),
    case Hit of
    {NewPos, object} ->
        io:fwrite("OBJECT"),
        gen_server:cast(Client, {updateBullet, {Direction, NewPos, self()}}),
        exit(normal);
    {NewPos, ID} ->
        io:fwrite("ID"),
        gen_server:cast(Client, {updateBullet, {Direction, NewPos, self()}}),
        ID ! {hit, Client},
        Client ! {frag, ID},
        exit(normal);
    {NewPos, move} ->
        io:fwrite("MOVE"),
        gen_server:cast(Client, {updateBullet, {Direction, NewPos, self()}})
    end,
    {noreply, {Direction, NewPos, ClientMaster}}.

terminate(_Reason, {_Direction, {_StartPos, _Size, Client}, _ClientMaster}) ->
    gen_server:cast(Client, {removeBullet, self()}),
    io:fwrite("bullet ~p terminated!\n", [self()]),
    ok.

你启动“中继器”的方式是错误的。按照它的编写方式,每个中继器消息将在100毫秒后到达您的进程邮箱(加上调用中继器本身的任何延迟)

您只需将
计数器
乘以正在使用的超时时间即可解决此问题。例如:

repeater(0) ->
    ok; % don't exit here; exit after you *receive* the last forward message
repeater(Counter) ->
    io:fwrite("REPEATER\n"),
    erlang:send_after(100 * Counter, self(), forward),
    repeater(Counter-1).
使用此选项,您将收到
计数器
转发消息,每个消息间隔大约100毫秒

请注意:1)Erlang不是大多数游戏开发的理想选择(例如,MMO服务器除外);2) 如果您坚持使用Erlang,请不要将单个项目符号表示为不同的进程。如果您试图使用计时器协调表示游戏对象的数千个进程,您将非常、非常快地遇到问题。你最好使用一个更传统的游戏循环,因为从一点开始比从一千点开始更容易管理时间。