课外价值不同

时间:2011-11-29 02:42:55

标签: c# .net

在我的联网游戏的代码中,客户端接收一个消息,即玩家实体由用户控制或仅由服务器控制。

UserControlled = msg.ReadBoolean();

此变量设置绝对没有其他位置,除非使用默认值false进行实例化。我使用Visual C#中的“查找所有引用”功能对此进行了双重检查。此外,在此语句的范围内没有具有相同名称的局部变量。我发现在上述陈述的范围内,一切都是发现和花花公子;变量设置为true,如之后直接将其打印到控制台所示。此时,奇怪的事情发生了。每次从我的播放器类的外部引用变量时,它都会正确显示为true - 但是只要从播放器代码中引用它,它就会返回布尔值实例化的默认值;无论是真还是假。

我对这个问题一无所知,任何可能导致解决方案的信息都非常感激:)

如果您想要更多代码,我当然可以提供。我只是不确定除变量的随机引用之外还包括什么,所以我决定将它们排除在外。

谢谢!

编辑更多代码:

UserControlled被定义为普通的类范围变量。

public bool UserControlled = false;

设置值的方法:

public override void ParseUpdateMsg(NetIncomingMessage msg) 
        {
            switch (msg.ReadByte())
            {
                case 0: // positional message
                    //snip
                    break;
                case 1: // other info
                    // The following simply reads in the information
                    // I'm using Lidgren Network Library. It's extensively tested so I don't suspect that it's the issue
                    Speed = msg.ReadInt16();
                    Username = msg.ReadString();
                    UserControlled = msg.ReadBoolean();
                    MovingDir = msg.ReadString();
                    Health = msg.ReadInt16();
                    Hunger = msg.ReadInt16();
                    Mana = msg.ReadInt16();
                    // The following is simply debugging information to the screen
                    // As said above, UserControlled at this point is correctly displayed as True
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("--------------------------");
                    Console.WriteLine("Update message received!");
                    Console.WriteLine("ID: " + ID + "\tType: " + this.GetType().ToString());
                    Console.WriteLine("Speed: " + Speed);
                    Console.WriteLine("Username: " + Username);
                    Console.WriteLine("UserControlled: " + UserControlled);
                    Console.WriteLine("MovingDir: " + MovingDir);
                    Console.WriteLine("--------------------------");
                    Console.ForegroundColor = ConsoleColor.White;
                    break;
            }
        }

以下是接收消息并将其传递给播放器实体以进行评估的客户端代码:

switch (msg.ReadInt16())
            {
                case 1:
                    // Entity message
                    switch (msg.ReadByte())
                    {
                        case 0: // Create entity
                            //snip
                            break;
                        case 1: // Update entity
                            int id1 = msg.ReadInt16();
                            Entities[id1].ParseUpdateMsg(msg); // the player entity is passed the information
                            // At this point, there is only one entity, and that is the player.
                            // More debug information. Still displayed correctly as true.
                            Console.ForegroundColor = ConsoleColor.Magenta;
                            Console.WriteLine("--------------------------");
                            Console.WriteLine("-analysis 1-");
                            Console.WriteLine("(Within scope of update-entity message)");
                            Console.WriteLine("UserControlled: " + ((ClientEntPlayer)Entities[id1]).UserControlled);
                            Console.WriteLine("--------------------------");
                            Console.ForegroundColor = ConsoleColor.White;
                            break;
                        case 2: // Destroy entity
                            //snip
                            break;
                    }
                    // Displayed correctly here as well!
                    Console.ForegroundColor = ConsoleColor.Magenta;
                    Console.WriteLine("--------------------------");
                    Console.WriteLine("-Post-analysis 2-");
                    Console.WriteLine("(Within scope of generic entity message)");
                    Console.WriteLine("UserControlled: " + player.UserControlled);
                    Console.WriteLine("--------------------------");
                    Console.ForegroundColor = ConsoleColor.White;
                    break;
            }

设置值后,上面的所有调试代码都会正确显示为True。但是,一旦我们开始进入定时检查,它就开始变得不正确(但仍然只是来自玩家的代码!)

以下内容来自客户的更新代码。它每5秒正确显示一次UserControlled值。

if (gameTime.TotalGameTime.Seconds % 5 == 0 && player != null && debugTime != gameTime.TotalGameTime.Seconds)
            {
                Console.ForegroundColor = ConsoleColor.DarkMagenta;
                Console.WriteLine("--------------------------");
                Console.WriteLine("Client's Timed Post-Analysis");
                Console.WriteLine("Elapsed time: " + gameTime.TotalGameTime.Seconds + " sec");
                Console.WriteLine("(Within scope of client update)");
                Console.WriteLine("UserControlled: " + player.UserControlled);
                Console.WriteLine("--------------------------");
                Console.ForegroundColor = ConsoleColor.White;
                debugTime = gameTime.TotalGameTime.Seconds;
            }

这是表示在离开功能后玩家的值不正确的部分。它显示为false(以及依赖于被控制的播放器的其他代码,如响应键盘输入。)它与客户端的定时调试信息基本相同,只是在播放器的更新功能中。

if (gameTime.TotalGameTime.Seconds % 5 == 0 && debugTime != gameTime.TotalGameTime.Seconds)
            {
                Console.ForegroundColor = ConsoleColor.DarkYellow;
                Console.WriteLine("--------------------------");
                Console.WriteLine("Player's Timed Post-Analysis");
                Console.WriteLine("(Within scope of player update)");
                Console.WriteLine("Elapsed time: " + gameTime.TotalGameTime.Seconds +" sec");
                Console.WriteLine("UserControlled: " + UserControlled);
                Console.WriteLine("--------------------------");
                Console.ForegroundColor = ConsoleColor.White;
                debugTime = gameTime.TotalGameTime.Seconds;
            }

就是这样。谢谢你的帮助。

2 个答案:

答案 0 :(得分:1)

由于缺少代码,这很难回答,但与此同时,无论如何发布所有代码都是不切实际的。

我大多数时候都是偶然地做过这件事,会在另一个范围内声明另一个变量,然后设置一个而不是我想要的变量。

所以,看起来代码只是设置在那个区域,但这也可能就是为什么你的“查找所有引用”只能找到那个位置。我会尝试右键单击UserControlledmsg变量,然后选择Go to declaration。也许你会发现你正在设置一个与你没想到的同名的不同变量。

如果UserControlled是类中的属性,您还可以尝试在其上设置断点。您可以右键单击断点并选择“When Hit ...”并将其设置为在其命中时打印堆栈跟踪及其值,而不是停止执行(我假设这是一个游戏,您可能不会希望/轻松地能够停止并继续执行。)

答案 1 :(得分:1)

正如我上面的评论所说,我无法告诉你发生了什么,但只能提供有关如何调试的建议。

首先,您说您已经检查了这一点但确保设置正确的UserControlled。如果它是该类的成员(假设它是属性?),则在其前面添加this.

this.UserControlled = msg.ReadBoolean(); 

根据我在您的问题中的理解,UserControlled在课堂内被询问时是 true ,但是当从课堂外查询时, false 。这只能是两件事:

  1. 您有两种不同的属性,或者由于副作用,属性的评估方式不同。
  2. 您有两个班级实例
  3. 为了进一步调查,你的财产是否正在做任何聪明的事情 - 即是否正在做其他任何设置和获得支持领域?你确定你正在使用你班级的单个实例吗?