function PlayerHand:post_init()
	local unit = self._unit
	local camera = unit:camera()
	local camera_unit = camera:camera_unit()
	local controller = unit:base():controller()
	local hand_states = {
		empty = EmptyHandState:new(),
		point = PointHandState:new(),
		weapon = WeaponHandState:new(),
		mask = MaskHandState:new(),
		item = ItemHandState:new(),
		ability = AbilityHandState:new(),
		equipment = EquipmentHandState:new(),
		akimbo = AkimboHandState:new(),
		tablet = TabletHandState:new(),
		belt = BeltHandState:new(),
		repeater = RepeaterHandState:new(),
		driving = DrivingHandState:new(),
		arrow = ArrowHandState:new()
	}
	self._hand_state_machine = HandStateMachine:new(hand_states, hand_states.empty, hand_states.empty)

	self._hand_state_machine:attach_controller(controller, true)
	self._hand_state_machine:attach_controller(managers.menu:get_controller())
	managers.vr:set_hand_state_machine(self._hand_state_machine)

	self._controller = controller
	self._vr_controller = controller:get_controller("vr")
	local base_rotation = camera_unit:base():base_rotation()
	self._base_rotation = base_rotation
	self._unit_movement_ext = unit:movement()
	self._camera_unit = camera_unit
	self._belt_yaw = base_rotation:yaw()
	self._prev_ghost_position = mvector3.copy(self._unit_movement_ext:ghost_position())
	self._hand_data = {}

	local vr_left = "units/pd2_dlc_vr/player/vr_hand_left"
	local vr_right = "units/pd2_dlc_vr/player/vr_hand_right"
	if(managers.dlc:is_dlc_unlocked("pgo")) then
		vr_left = "units/pd2_dlc_vr/player/vr_hand_left_kids"
		vr_right = "units/pd2_dlc_vr/player/vr_hand_right_kids"
	end

	local l_hand_unit = World:spawn_unit(Idstring(vr_left), Vector3(0, 0, 0), Rotation())
	local r_hand_unit = World:spawn_unit(Idstring(vr_right), Vector3(0, 0, 0), Rotation())

	l_hand_unit:base():set_other_hand_unit(r_hand_unit)
	r_hand_unit:base():set_other_hand_unit(l_hand_unit)
	l_hand_unit:warp():set_player_unit(unit)
	r_hand_unit:warp():set_player_unit(unit)

	self._shadow_unit = World:spawn_unit(Idstring("units/pd2_dlc_vr/player/vr_shadow"), Vector3(0, 0, 0), Rotation())

	unit:link(l_hand_unit)
	unit:link(r_hand_unit)
	unit:link(self._shadow_unit)

	local controller_rotation = Rotation()

	if managers.vr:is_oculus() then
		controller_rotation = Rotation(math.X, -30)
	end

	table.insert(self._hand_data, {
		hand = "right",
		state = "idle",
		unit = r_hand_unit,
		base_rotation = Rotation(math.X, -50),
		base_rotation_controller = controller_rotation,
		base_position = Vector3(0, -2, -7),
		base_position_finger = Vector3(3.5, 11, 3.5),
		position = Vector3(),
		finger_position = Vector3(),
		rotation = Rotation(),
		rotation_raw = Rotation(),
		prev_position = Vector3(),
		prev_rotation = Rotation()
	})
	table.insert(self._hand_data, {
		hand = "left",
		state = "idle",
		unit = l_hand_unit,
		base_rotation = Rotation(math.X, -50),
		base_rotation_controller = controller_rotation,
		base_position = Vector3(0, -2, -7),
		base_position_finger = Vector3(-3.5, 11, 3.5),
		position = Vector3(),
		finger_position = Vector3(),
		rotation = Rotation(),
		rotation_raw = Rotation(),
		prev_position = Vector3(),
		prev_rotation = Rotation()
	})
	r_hand_unit:base():set_hand_data(self._hand_data[1])
	l_hand_unit:base():set_hand_data(self._hand_data[2])

	self._watch = PlayerWatch:new(l_hand_unit)
	self._shared_transition_queue = StateMachineTransitionQueue:new()
	self._hand_data[PlayerHand.RIGHT].state_machine = PlayerHandStateMachine:new(self._hand_data[PlayerHand.RIGHT].unit, PlayerHand.RIGHT, self._shared_transition_queue)
	self._hand_data[PlayerHand.LEFT].state_machine = PlayerHandStateMachine:new(self._hand_data[PlayerHand.LEFT].unit, PlayerHand.LEFT, self._shared_transition_queue)

	self._hand_data[PlayerHand.RIGHT].state_machine:set_other_hand(self._hand_data[PlayerHand.LEFT].state_machine)
	self._hand_data[PlayerHand.LEFT].state_machine:set_other_hand(self._hand_data[PlayerHand.RIGHT].state_machine)

	self._belt_unit = World:spawn_unit(Idstring("units/pd2_dlc_vr/player/vr_hud_belt"), Vector3(0, 0, 0), Rotation())

	self._belt_unit:set_visible(false)

	self._float_unit = World:spawn_unit(Idstring("units/pd2_dlc_vr/player/vr_hud_belt"), Vector3(0, 0, 0), Rotation())

	self._float_unit:set_visible(false)

	local default_weapon_hand = self.hand_id(managers.vr:get_setting("default_weapon_hand") or "right")
	local default_tablet_hand = self.hand_id(managers.vr:get_setting("default_tablet_hand") or "left")

	managers.hud:bind_hud_to_vr_hand(self:hand_unit(default_weapon_hand), self:hand_unit(default_tablet_hand), self._belt_unit, default_weapon_hand, default_tablet_hand, self._float_unit)
	self._hand_data[default_weapon_hand].state_machine:set_default_state("weapon")
	self._hand_data[self.other_hand_id(default_tablet_hand)].unit:damage():run_sequence_simple("hide_gadgets")

	self._tablet_hand_changed_clbk = callback(self, self, "on_tablet_hand_changed")

	managers.vr:add_setting_changed_callback("default_tablet_hand", self._tablet_hand_changed_clbk)

	self._belt_size_changed_clbk = callback(self, self, "on_belt_size_changed")

	managers.vr:add_setting_changed_callback("belt_size", self._belt_size_changed_clbk)

	self._default_weapon_hand_changed_clbk = callback(self, self, "on_default_weapon_hand_changed")

	managers.vr:add_setting_changed_callback("default_weapon_hand", self._default_weapon_hand_changed_clbk)

	self._weapon_hand_id = default_weapon_hand
	self._arm_peer_filter = self._arm_peer_filter or {}
	self._arm_simulator = ArmSimulator:new("gamedata/arms", self._vr_controller)
	self._sync_listener_key = {}

	managers.network:add_event_listener(self._sync_listener_key, "session_peer_sync_complete", callback(self, self, "on_peer_sync_complete"))

	self._arm_animation_changed_clbk = callback(self, self, "on_arm_animation_changed")

	managers.vr:add_setting_changed_callback("arm_animation", self._arm_animation_changed_clbk)
end
