Skip to content

Game.Prefabs.PlaceableObjectData

Assembly: Assembly-CSharp.dll (Game code)
Namespace: Game.Prefabs

Type: struct

Base: Unity.Entities.IComponentData, Unity.Entities.IQueryTypeParameter, Colossal.Serialization.Entities.ISerializable

Summary:
PlaceableObjectData is an ECS component/serializable struct that holds basic placement-related data for placeable objects in Cities: Skylines 2. It contains placement offset, construction cost, XP reward and placement flags. The struct implements custom serialization/deserialization via ISerializable so selected fields can be read/written to the game's binary serializers and used in entity queries via IQueryTypeParameter.


Fields

  • public float3 m_PlacementOffset
    Stores the local placement offset (x,y,z) applied when placing the object. This value is serialized/deserialized.

  • public uint m_ConstructionCost
    The construction cost (currency) for placing the object. This value is serialized/deserialized.

  • public int m_XPReward
    Experience points awarded when the object is placed. This value is serialized/deserialized.

  • public byte m_DefaultProbability
    Default spawn/selection probability byte. NOTE: this field is present in the struct but is not used in the current Serialize/Deserialize implementation (it is not written/read).

  • public RotationSymmetry m_RotationSymmetry
    Rotation symmetry enum describing allowed rotations for placement. NOTE: not serialized/deserialized by the supplied implementation; defined elsewhere (likely in Game.Objects).

  • public SubReplacementType m_SubReplacementType
    Sub-replacement type enum (used for replacement variants). NOTE: not serialized/deserialized here.

  • public Game.Objects.PlacementFlags m_Flags
    Flags controlling placement behavior. During deserialization the raw uint is read and masked with a specific mask to clear a particular bit (see Deserialize notes). When serializing the flags are written as a uint.

Properties

  • None (this struct exposes fields directly; no C# properties are declared).

Constructors

  • public PlaceableObjectData() (implicit default struct constructor)
    No custom constructors are defined; use object initializer syntax to set fields.

Methods

  • public void Deserialize<TReader>(TReader reader) where TReader : IReader
    Reads serialized data into the struct. Implementation details:
  • Reads m_PlacementOffset (float3)
  • Reads m_ConstructionCost (uint)
  • Reads m_XPReward (int)
  • Reads a raw uint value and assigns m_Flags = (PlacementFlags)((int)value & -32769)
    • The mask "& -32769" clears the bit corresponding to 0x8000 (decimal 32768). This strips that specific bit from the raw value before casting to PlacementFlags. This is likely done for backward compatibility or to discard a deprecated/unused flag bit.

Note: Several fields (m_DefaultProbability, m_RotationSymmetry, m_SubReplacementType) are not read by this method.

  • public void Serialize<TWriter>(TWriter writer) where TWriter : IWriter
    Writes selected fields to the serializer:
  • Writes m_PlacementOffset (float3)
  • Writes m_ConstructionCost (uint)
  • Writes m_XPReward (int)
  • Writes m_Flags cast to uint

Note: The serializer does not write m_DefaultProbability, m_RotationSymmetry or m_SubReplacementType in this implementation.

Usage Example

// Create and add this component to an entity with EntityManager
var placeable = new Game.Prefabs.PlaceableObjectData {
    m_PlacementOffset = new Unity.Mathematics.float3(0f, 0.5f, 0f),
    m_ConstructionCost = 100u,
    m_XPReward = 10,
    m_DefaultProbability = 255,
    m_RotationSymmetry = RotationSymmetry.FourWay,
    m_SubReplacementType = SubReplacementType.None,
    m_Flags = Game.Objects.PlacementFlags.AllowOnWater
};

entityManager.AddComponentData(entity, placeable);

// Note: serialization is handled by the game's reader/writer pipeline via the ISerializable implementation.
// If you implement custom readers/writers, ensure you match the same order and masking behavior used in Deserialize/Serialize.

Notes for modders: - Because some fields in the struct are not serialized, they may be used only at runtime or set programmatically by other systems. If you need to persist those fields across save/load, consider updating the serialization implementation (modifying game assemblies or using patched serializers) — be careful with compatibility. - The flag-mask in Deserialize indicates a deliberate exclusion of one bit. Avoid changing that behavior unless you understand the historical/compatibility reason for it.