Forum Discussion

Telejavi's avatar
Telejavi
Member
9 months ago

Issue accessing player position using world.getLocalPlayer()

Hello! I'm new to scripting using Typescript in the desktop editor and I've run into a problem that I haven't quite been able to solve. I saw code snippets and suggestions about using world.getLocalPlayer() but it's not quite working for me. When I call that method, the resulting player has an empty name and trying to access its position with player.position.get() gives an error. 

Here's the code that isn't working, inside Start : 

const player = this.world.getLocalPlayer(); 

console.log(`local player name: ${player.name.get()}`);
console.log(`local player id: ${player.id}`);
console.log(`local player exists?: ${player}`);
if (player) {
//const position = player.position.get(); //this line gives an error when uncommented
//console.log(`Player position: ${position.x}, ${position.y}, ${position.z}`);
}

Here's the console output for that, when the error is commented out: 

Here's the error if I attempt to access the position:

It may be something silly, but I have no idea what's wrong! 

I also tried using a player map (code below) that I found and that does work and give me my name and position, however I don't know how I could use that without knowing who is the local player. 

this.connectCodeBlockEvent(
this.entity,
hz.CodeBlockEvents.OnPlayerEnterWorld,
(player: hz.Player) => {
this.playerMap.set(player.id, player);
console.log(`added player: ${player.name.get()}`);
const position = player.position.get();
console.log(`Player id: ${player.id}`);
console.log(`Player position: ${position.x}, ${position.y}, ${position.z}`); //this DOES work unlike the other code
},
);

 If anyone's able to help I'd be grateful! Thanks for reading

18 Replies

    • Telejavi's avatar
      Telejavi
      Member

      Just after posting I saw that was an option - it didn't help. I'd also tested with getServerPlayer and it was unsuccessful, both returned the same empty-ish player.

  • You will still need to transferer ownership of the object/script to a player to get the local player.

         * @remarks This is particularly useful for Local Scripting to figure out which
         * player's machine a local script is executing on. Note that if the local script
         * is executing on the server, this will return the server player.
         * @returns The local player.
    • Telejavi's avatar
      Telejavi
      Member

      I see, thanks. But getting the server player also failed so I'm not sure what is hapening. I'll look into transferring the ownership though!

      • gausroth's avatar
        gausroth
        Mentor

        getServerPlayer() returns a player that is not a real player.
        getLocalPlayer() returns the owner of a locally scripted object.

        Can you share your use case?

  • Yea its odd that it does not state that it has to be on a local script that already has an owner. Perhaps this is a candidate for a document correction.

    Try this:

    NOTE: This script must be set to local.

     

     

     

     

    import { Component, Player, CodeBlockEvents } from "horizon/core";
    
    class GetPlayerPosition extends Component {
    
         private activePlayer: Player | undefined;
    
         preStart() {
              this.connectCodeBlockEvent(this.entity, CodeBlockEvents.OnPlayerEnterWorld, this.playerEnterWorld.bind(this));
         }
    
         playerEnterWorld(player: Player) {
              this.entity.owner.set(player)
         }
    
         start() {
              // when you transfer ownership the script resets and start is called
              this.activePlayer = this.entity.owner.get();
              if(this.activePlayer != this.world.getServerPlayer()){
                   const position = this.activePlayer.position.get();
                   console.log(`Player position: ${position.x}, ${position.y}, ${position.z}`);
              }
         }
    }
    Component.register(GetPlayerPosition);

     

     

     

     

     

    • Telejavi's avatar
      Telejavi
      Member

      I can't compile that, not sure if I was meant to copy it literally or put it inside something else

  • The 'local player' is the player running the script. For default scripts, it is _always_ the server player. The server player has no name, and is not a 'real' player like humans or Avatar NPCs.  You will need to get a 'real' Player variable from somewhere in order ask what that player's position is. 

    You _could_ create script with 'local' execution mode, and then attach it to an entity that you then transfer to a Player. Then the 'local player' would be that real Player that owns the entity that hosts the script. But... you need a Player object to do that transfer, and if you have that, why not just ask that Player object for its position rather than doing all the rigamarole of 'local' scripts?

    You can get Player objects via various events, like OnPlayerEnterWorld, OnPlayerEnterTrigger, OnPlayerCollision, etc.

    • Telejavi's avatar
      Telejavi
      Member

      Okay! So the suggested method to get the local player would be to use an event in a locally run script? That can work, but it also feels like a bit of a workaround (and it would mean the documentation is at best imprecise if it's saying that we should use getLocalPlayer).

      I'd have to think about what happens if someone else joins later and triggers the same event, but I imagine if it's a local script it would be fine. In any case, just being able to playtest some single-player stuff is good for now, as I know dealing with client-server architectures can make things significantly harder. 

      Thanks for the informative answer!

      • Shards632's avatar
        Shards632
        Mentor

        You should not use local execution mode scripts unless you have specific needs for the capabilities of local scripts (as they also come with significant limitations). Until you get used to HZW scripting, I would stick to default execution mode scripts that run on the server.  You will need to track your Player in variables via delivered events rather than trying to get it 'out of the air' from the scripting execution environment. For 'default' execution mode scripts, the 'local' player is always the server, so never what you want. This will force you to track the Player you actually want correctly.