UDN
Search public documentation:

ReplicationProxyCH
English Translation
日本語訳
한국어

Interested in the Unreal Engine?
Visit the Unreal Technology site.

Looking for jobs and company info?
Check out the Epic games site.

Questions about support via UDN?
Contact the UDN Staff

UE3 主页 > 网络&复制 >代理模式

代理模式


概述


当您有一些不存在于客户端上但客户端需要看到或听到它们声音的actor或对象时使用这个代理模式。因为这些actors不存在于客户端上,所以服务器没有办法把它们直接复制到客户端上。而且对象根本就支持复制。那么您可以使用代理模式来模拟actor或对象在服务器上的行为,在客户端上通过代理来查看它们,不需要复制代理本身。

武器附加物


在虚幻竞技场3的武器附加物中应用了该模式。虚幻引擎3中的武器仅和服务器及拥有那个武器的客户端有关。但是,其他客户端也需要知道一些关于那个客户端正在挥舞操作的武器的一些信息。这可以通过在服务器上创建该武器附加物然后将它复制到所有客户端上实现。这样服务器和客户端就都可以产生武器附加物actor了。当在服务器上更新武器时,武器将把这些改变告诉pawn拥有者。然后,将会把这些改变复制到客户端来更新客户端的武器附加物。

UTPawn.uc
var repnotify class<UTWeaponAttachment> CurrentWeaponAttachmentClass;
var UTWeaponAttachment CurrentWeaponAttachment;

replication
{
  if (bNetDirty)
    CurrentWeaponAttachmentClass;
}

simulated event ReplicatedEvent(name VarName)
{
  if (VarName == 'CurrentWeaponAttachmentClass')
  {
    WeaponAttachmentChanged();
  }
}

simulated function WeaponAttachmentChanged()
{
  if ((CurrentWeaponAttachment == None || CurrentWeaponAttachment.Class != CurrentWeaponAttachmentClass) && Mesh.SkeletalMesh != None)
  {
    if (CurrentWeaponAttachment!=None)
    {
      CurrentWeaponAttachment.DetachFrom(Mesh);
      CurrentWeaponAttachment.Destroy();
    }

    if (CurrentWeaponAttachmentClass!=None)
    {
      CurrentWeaponAttachment = Spawn(CurrentWeaponAttachmentClass,self);
      CurrentWeaponAttachment.Instigator = self;
    }
    else
      CurrentWeaponAttachment = none;

    if (CurrentWeaponAttachment != None)
    {
      CurrentWeaponAttachment.AttachTo(self);
      CurrentWeaponAttachment.SetSkin(ReplicatedBodyMaterial);
      CurrentWeaponAttachment.ChangeVisibility(bWeaponAttachmentVisible);
    }
  }
}

simulated function WeaponFired(Weapon InWeapon, bool bViaReplication, optional vector HitLocation)
{
  if (CurrentWeaponAttachment != None)
  {
    if (!IsFirstPerson())
    {
      CurrentWeaponAttachment.ThirdPersonFireEffects(HitLocation);
    }
    else
    {
      CurrentWeaponAttachment.FirstPersonFireEffects(Weapon, HitLocation);

      if (class'Engine'.static.IsSplitScreen() && CurrentWeaponAttachment.EffectIsRelevant(CurrentWeaponAttachment.Location, false, CurrentWeaponAttachment.MaxFireEffectDistance))
      {
        CurrentWeaponAttachment.CauseMuzzleFlash();
      }
    }

    if (HitLocation != Vect(0,0,0) && (WorldInfo.NetMode == NM_ListenServer || WorldInfo.NetMode == NM_Standalone || bViaReplication))
    {
      CurrentWeaponAttachment.PlayImpactEffects(HitLocation);
    }
  }
}

UTWeaponAttachment.uc
simulated function CauseMuzzleFlash()
{
  local ParticleSystem MuzzleTemplate;

  if ((!WorldInfo.bDropDetail && !class'Engine'.static.IsSplitScreen()) || WorldInfo.IsConsoleBuild(CONSOLE_Mobile))
  {
    if (MuzzleFlashLight == None)
    {
      if (MuzzleFlashLightClass != None)
      {
        MuzzleFlashLight = new(Outer) MuzzleFlashLightClass;

        if (Mesh != None && Mesh.GetSocketByName(MuzzleFlashSocket) != None)
        {
          Mesh.AttachComponentToSocket(MuzzleFlashLight, MuzzleFlashSocket);
        }
        else if (OwnerMesh != None)
        {
          OwnerMesh.AttachComponentToSocket(MuzzleFlashLight, AttachmentSocket);
        }
      }
    }
    else
    {
      MuzzleFlashLight.ResetLight();
    }
  }

  if (MuzzleFlashPSC != none)
  {
    if (!bMuzzleFlashPSCLoops || !MuzzleFlashPSC.bIsActive)
    {
      if (Instigator != None && Instigator.FiringMode == 1 && MuzzleFlashAltPSCTemplate != None)
      {
        MuzzleTemplate = MuzzleFlashAltPSCTemplate;
      }
      else
      {
        MuzzleTemplate = MuzzleFlashPSCTemplate;
      }

      if (MuzzleTemplate != MuzzleFlashPSC.Template)
      {
        MuzzleFlashPSC.SetTemplate(MuzzleTemplate);
      }

      SetMuzzleFlashParams(MuzzleFlashPSC);
      MuzzleFlashPSC.ActivateSystem();
    }
  }

  SetTimer(MuzzleFlashDuration, false, 'MuzzleFlashTimer');
}

simulated function ThirdPersonFireEffects(vector HitLocation)
{
  local UTPawn P;

  if (EffectIsRelevant(Location,false,MaxFireEffectDistance))
  {
    CauseMuzzleFlash();
  }

  P = UTPawn(Instigator);
  if (P != None && P.GunRecoilNode != None)
  {
    P.GunRecoilNode.bPlayRecoil = true;
  }

  if (Instigator.FiringMode == 1 && AltFireAnim != 'None')
  {
    Mesh.PlayAnim(AltFireAnim,,, false);
  }
  else if (FireAnim != 'None')
  {
    Mesh.PlayAnim(FireAnim,,, false);
  }
}

注意

UTPawn和UTWeaponAttachment都仅显示特定的函数,请查看源码文件来获得完整逻辑。

结论


仅当客户端需要看到或听到不存在于该客户端上的actor或对象的特效时使用该模式。除武器附加物外,可以应用的该模式的其他情况有:
  • 具有游戏性效果的 防具/布料 附加物。
  • 具有游戏性效果的车辆上的炮塔附加物。