> For the complete documentation index, see [llms.txt](https://kinematicsoup.gitbook.io/scene-fusion/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kinematicsoup.gitbook.io/scene-fusion/api-reference/ks.scenefusion.client/ks.scenefusion.client.sfobject.md).

# Class sfObject

Namespace: [KS.SceneFusion.Client](/scene-fusion/api-reference/ks.scenefusion.client.md)\
Assembly: KSUnity-Editor.dll

Objects are synced between server and clients. Objects have an id, a user-defined string type, and a property which may be a collection of properties. Objects are arranged in a hierarchy and can be locked by users. When objects are constructed they are not automatically synced. To begin syncing an object, call sfSession.Create(sfObject).

```csharp
public class sfObject : sfBaseObject<sfObject>
```

#### Inheritance

object ← ksHierarchyObject\<sfObject> ← [sfBaseObject\<sfObject>](/scene-fusion/api-reference/ks.scenefusion/ks.scenefusion.sfbaseobject-1.md) ← [sfObject](/scene-fusion/api-reference/ks.scenefusion.client/ks.scenefusion.client.sfobject.md)

#### Inherited Members

[sfBaseObject\<sfObject>.Id](/scene-fusion/api-reference/ks.scenefusion/ks.scenefusion.sfbaseobject-1.md#ks_scenefusion_sfbaseobject_1_id), [sfBaseObject\<sfObject>.Type](/scene-fusion/api-reference/ks.scenefusion/ks.scenefusion.sfbaseobject-1.md#ks_scenefusion_sfbaseobject_1_type), [sfBaseObject\<sfObject>.Flags](/scene-fusion/api-reference/ks.scenefusion/ks.scenefusion.sfbaseobject-1.md#ks_scenefusion_sfbaseobject_1_flags), [sfBaseObject\<sfObject>.Property](/scene-fusion/api-reference/ks.scenefusion/ks.scenefusion.sfbaseobject-1.md#ks_scenefusion_sfbaseobject_1_property), [sfBaseObject\<sfObject>.DirectLockOwnerId](/scene-fusion/api-reference/ks.scenefusion/ks.scenefusion.sfbaseobject-1.md#ks_scenefusion_sfbaseobject_1_directlockownerid), [sfBaseObject\<sfObject>.m\_directLockOwnerId](/scene-fusion/api-reference/ks.scenefusion/ks.scenefusion.sfbaseobject-1.md#ks_scenefusion_sfbaseobject_1_m_directlockownerid), [sfBaseObject\<sfObject>.PerformAddChild(sfObject)](/scene-fusion/api-reference/ks.scenefusion/ks.scenefusion.sfbaseobject-1.md#ks_scenefusion_sfbaseobject_1_performaddchild__0), [sfBaseObject\<sfObject>.PerformInsertChild(int, sfObject)](/scene-fusion/api-reference/ks.scenefusion/ks.scenefusion.sfbaseobject-1.md#ks_scenefusion_sfbaseobject_1_performinsertchild_system_int32__0), [sfBaseObject\<sfObject>.PerformRemoveChild(sfObject)](/scene-fusion/api-reference/ks.scenefusion/ks.scenefusion.sfbaseobject-1.md#ks_scenefusion_sfbaseobject_1_performremovechild__0), [sfBaseObject\<sfObject>.ToString()](/scene-fusion/api-reference/ks.scenefusion/ks.scenefusion.sfbaseobject-1.md#ks_scenefusion_sfbaseobject_1_tostring), [sfBaseObject\<sfObject>.Print(bool)](/scene-fusion/api-reference/ks.scenefusion/ks.scenefusion.sfbaseobject-1.md#ks_scenefusion_sfbaseobject_1_print_system_boolean), [sfBaseObject\<sfObject>.FindAncestor(string, bool)](/scene-fusion/api-reference/ks.scenefusion/ks.scenefusion.sfbaseobject-1.md#ks_scenefusion_sfbaseobject_1_findancestor_system_string_system_boolean), [sfBaseObject\<sfObject>.GetLockOwnerId()](/scene-fusion/api-reference/ks.scenefusion/ks.scenefusion.sfbaseobject-1.md#ks_scenefusion_sfbaseobject_1_getlockownerid), [sfBaseObject\<sfObject>.IncrementPartialLockCounts(sfObject)](/scene-fusion/api-reference/ks.scenefusion/ks.scenefusion.sfbaseobject-1.md#ks_scenefusion_sfbaseobject_1_incrementpartiallockcounts__0), [sfBaseObject\<sfObject>.IncrementFullLockCounts(sfObject)](/scene-fusion/api-reference/ks.scenefusion/ks.scenefusion.sfbaseobject-1.md#ks_scenefusion_sfbaseobject_1_incrementfulllockcounts__0)

## Constructors

### sfObject(string, sfBaseProperty, ObjectFlags) <a href="#ks_scenefusion_client_sfobject__ctor_system_string_ks_scenefusion_sfbaseproperty_ks_scenefusion_sfba" id="ks_scenefusion_client_sfobject__ctor_system_string_ks_scenefusion_sfbaseproperty_ks_scenefusion_sfba"></a>

Constructor

```csharp
public sfObject(string type, sfBaseProperty property = null, sfBaseObject<sfObject>.ObjectFlags flags = ObjectFlags.NONE)
```

#### Parameters

`type` string

type of object.

`property` [sfBaseProperty](/scene-fusion/api-reference/ks.scenefusion/ks.scenefusion.sfbaseproperty.md)

`flags` [sfBaseObject](/scene-fusion/api-reference/ks.scenefusion/ks.scenefusion.sfbaseobject-1.md)<[sfObject](/scene-fusion/api-reference/ks.scenefusion.client/ks.scenefusion.client.sfobject.md)>.[ObjectFlags](/scene-fusion/api-reference/ks.scenefusion/ks.scenefusion.sfbaseobject-1/ks.scenefusion.sfbaseobject-1.objectflags.md)

flags of object. If UNSUBSCRIBED is set, it is cleared; the server controls that flag and the user who creates the object always starts subscribed to it.

## Properties

### CanEdit <a href="#ks_scenefusion_client_sfobject_canedit" id="ks_scenefusion_client_sfobject_canedit"></a>

Can we edit the object? Objects cannot be edited if they are locked by another user, if they are deleted locally and we're waiting for the server to resolve the delete request, if it has an id conflict, or while applying changes from the server unless the object is not syncing.

```csharp
public bool CanEdit { get; }
```

#### Property Value

bool

### CanEditChildren <a href="#ks_scenefusion_client_sfobject_caneditchildren" id="ks_scenefusion_client_sfobject_caneditchildren"></a>

Can we edit the children of this object? Objects cannot have their children edited if they are fully locked by another user (meaning that user directly locked the object or one of its ancestors), if they are deleted locally and we're waiting for the server to resolve the delete request, if it has an id conflict, if we are unsubscribed or unsubscribing from the object, or while applying changes from the server unless the object is not syncing.

```csharp
public bool CanEditChildren { get; }
```

#### Property Value

bool

### HasIdConflict <a href="#ks_scenefusion_client_sfobject_hasidconflict" id="ks_scenefusion_client_sfobject_hasidconflict"></a>

Does this object have an unresolved id conflict? If an object was created locally and we are waiting for the server to confirm the creation, but before we got confirmation, the server created another object with the same id, those objects have an id conflict and neither of them can be edited until the conflict is resolved, which will happen when the server acknowledges our create request and we delete the object we created locally because of the id conflict, or when the server deletes the other object with the same id.

```csharp
public bool HasIdConflict { get; }
```

#### Property Value

bool

### IsCreatePending <a href="#ks_scenefusion_client_sfobject_iscreatepending" id="ks_scenefusion_client_sfobject_iscreatepending"></a>

Are we waiting for the server to create this object?

```csharp
public bool IsCreatePending { get; }
```

#### Property Value

bool

### IsCreated <a href="#ks_scenefusion_client_sfobject_iscreated" id="ks_scenefusion_client_sfobject_iscreated"></a>

Is the object created on the server? This differs slightly from IsSyncing. When we send a create request, IsSyncing becomes true, but IsCreated becomes true when the server acknowledges the creation. Similarly when we send a delete request, IsSyncing becomes false but IsCreated becomes false when the server acknowledges the deletion.

```csharp
public bool IsCreated { get; }
```

#### Property Value

bool

### IsDeletePending <a href="#ks_scenefusion_client_sfobject_isdeletepending" id="ks_scenefusion_client_sfobject_isdeletepending"></a>

Are we waiting for the server to delete this object?

```csharp
public bool IsDeletePending { get; }
```

#### Property Value

bool

### IsFullyLocked <a href="#ks_scenefusion_client_sfobject_isfullylocked" id="ks_scenefusion_client_sfobject_isfullylocked"></a>

Is the object fully locked? Locked objects are either fully locked or partially locked. Partially locked objects can have their children edited and full locked objects cannot. An object is fully locked if it or one of its ancestors is locked directly. Otherwise if a descendant is locked directly, the object is partially locked.

```csharp
public bool IsFullyLocked { get; }
```

#### Property Value

bool

### IsLockPending <a href="#ks_scenefusion_client_sfobject_islockpending" id="ks_scenefusion_client_sfobject_islockpending"></a>

Are we waiting to acquire a lock on this object?

```csharp
public bool IsLockPending { get; }
```

#### Property Value

bool

### IsLockRequested <a href="#ks_scenefusion_client_sfobject_islockrequested" id="ks_scenefusion_client_sfobject_islockrequested"></a>

Do we want to own the lock on this object?

```csharp
public bool IsLockRequested { get; }
```

#### Property Value

bool

### IsLocked <a href="#ks_scenefusion_client_sfobject_islocked" id="ks_scenefusion_client_sfobject_islocked"></a>

Is the object locked directly or indirectly by another user?

```csharp
public bool IsLocked { get; }
```

#### Property Value

bool

### IsLockedDirectly <a href="#ks_scenefusion_client_sfobject_islockeddirectly" id="ks_scenefusion_client_sfobject_islockeddirectly"></a>

Is this object locked directly? An object is locked directly if another user called RequestLock() on the object.

```csharp
public bool IsLockedDirectly { get; }
```

#### Property Value

bool

### IsPartiallyLocked <a href="#ks_scenefusion_client_sfobject_ispartiallylocked" id="ks_scenefusion_client_sfobject_ispartiallylocked"></a>

Is the object partially locked? Locked objects are either fully locked or partially locked. Partially locked objects can have their children edited and fully locked objects cannot. An object is fully locked if it or one of its ancestors is locked directly. Otherwise if a descendant is locked directly, the object is partially locked.

```csharp
public bool IsPartiallyLocked { get; }
```

#### Property Value

bool

### IsSubscribed <a href="#ks_scenefusion_client_sfobject_issubscribed" id="ks_scenefusion_client_sfobject_issubscribed"></a>

Are we subscribed to receive the children of this object? This is always true for objects that do not require a subscription.

```csharp
public bool IsSubscribed { get; }
```

#### Property Value

bool

### IsSubscriptionChangePending <a href="#ks_scenefusion_client_sfobject_issubscriptionchangepending" id="ks_scenefusion_client_sfobject_issubscriptionchangepending"></a>

Are we waiting for the server to change our subscription status for this object?

```csharp
public bool IsSubscriptionChangePending { get; }
```

#### Property Value

bool

### IsSubscriptionRequested <a href="#ks_scenefusion_client_sfobject_issubscriptionrequested" id="ks_scenefusion_client_sfobject_issubscriptionrequested"></a>

Have we requested to be subscribed to receive the children of this object? This becomes true immediately when Subscribe is called, and false when Unsubscribe is called. Always true for objects that do not require a subscription.

```csharp
public bool IsSubscriptionRequested { get; }
```

#### Property Value

bool

### IsSyncing <a href="#ks_scenefusion_client_sfobject_issyncing" id="ks_scenefusion_client_sfobject_issyncing"></a>

Are changes to the object being synced? To begin syncing an object, call sfSession.Create(sfObject).

```csharp
public bool IsSyncing { get; }
```

#### Property Value

bool

### LockOwner <a href="#ks_scenefusion_client_sfobject_lockowner" id="ks_scenefusion_client_sfobject_lockowner"></a>

The user who owns the lock on this object, either directly or indirectly. A user will indirectly own a lock if they directly lock an ancestor of the object. Null if no user owns a lock on this object. The object may still be indirectly locked without a lock owner if one or more users own locks on descendants of the object.

```csharp
public sfUser LockOwner { get; }
```

#### Property Value

[sfUser](/scene-fusion/api-reference/ks.scenefusion.client/ks.scenefusion.client.sfuser.md)

### Property <a href="#ks_scenefusion_client_sfobject_property" id="ks_scenefusion_client_sfobject_property"></a>

Object property. May be a collection of properties.

```csharp
public override sfBaseProperty Property { get; set; }
```

#### Property Value

[sfBaseProperty](/scene-fusion/api-reference/ks.scenefusion/ks.scenefusion.sfbaseproperty.md)

### Session <a href="#ks_scenefusion_client_sfobject_session" id="ks_scenefusion_client_sfobject_session"></a>

Session the object belongs to.

```csharp
public sfSession Session { get; }
```

#### Property Value

[sfSession](/scene-fusion/api-reference/ks.scenefusion.client/ks.scenefusion.client.sfsession.md)

## Methods

### AddChild(sfObject) <a href="#ks_scenefusion_client_sfobject_addchild_ks_scenefusion_client_sfobject" id="ks_scenefusion_client_sfobject_addchild_ks_scenefusion_client_sfobject"></a>

Appends a child to this object. The child and this object must have the same syncing state. If the child has a different parent, removes it from its parent. Does nothing if this object is fully locked, the child is is locked, the child is already a child of this object, or adding the child would create a circular reference.

```csharp
public override bool AddChild(sfObject child)
```

#### Parameters

`child` [sfObject](/scene-fusion/api-reference/ks.scenefusion.client/ks.scenefusion.client.sfobject.md)

child to add.

#### Returns

bool

true if the child was added successfully. Note that this does not wait for a response from the server, so it may return true and be reverted later if another user gets a lock that prevents the child addition.

### FlushPropertyChanges() <a href="#ks_scenefusion_client_sfobject_flushpropertychanges" id="ks_scenefusion_client_sfobject_flushpropertychanges"></a>

Sends queued property changes for this object to the server. Property changes aren't sent immediately and instead are sent at regular intervals, or when the object's hierarchy changes or when the local user releases their lock on the object. Call this when you need to send property changes immediately.

```csharp
public void FlushPropertyChanges()
```

### GetCannotEditChildrenReason() <a href="#ks_scenefusion_client_sfobject_getcannoteditchildrenreason" id="ks_scenefusion_client_sfobject_getcannoteditchildrenreason"></a>

Gets a string with the reason the children of this object cannot be edited, or null if they can be edited.

```csharp
public string GetCannotEditChildrenReason()
```

#### Returns

string

reason the children cannot be edited, or null if they can be edited.

### GetCannotEditReason() <a href="#ks_scenefusion_client_sfobject_getcannoteditreason" id="ks_scenefusion_client_sfobject_getcannoteditreason"></a>

Gets a string with the reason this object cannot be edited, or null if the object can be edited.

```csharp
public string GetCannotEditReason()
```

#### Returns

string

reason the object cannot be edited, or null if it can be edited.

### InsertChild(int, sfObject) <a href="#ks_scenefusion_client_sfobject_insertchild_system_int32_ks_scenefusion_client_sfobject" id="ks_scenefusion_client_sfobject_insertchild_system_int32_ks_scenefusion_client_sfobject"></a>

Inserts a child at an index on this object. The child and this object must have the same syncing state. If the child has a different parent, removes it from its parent. Does nothing if this object is fully locked, the child is locked, the child is already a child of this object, or inserting the child would create a circular reference.

```csharp
public override bool InsertChild(int index, sfObject child)
```

#### Parameters

`index` int

index to insert child at.

`child` [sfObject](/scene-fusion/api-reference/ks.scenefusion.client/ks.scenefusion.client.sfobject.md)

child to insert.

#### Returns

bool

true if the child was inserted successfully. Note that this does not wait for a response from the server, so it may return true and be reverted later if another user gets a lock that prevents the child insertion.

### ReleaseLock() <a href="#ks_scenefusion_client_sfobject_releaselock" id="ks_scenefusion_client_sfobject_releaselock"></a>

Releases the lock on this object, or stops trying to acquire the lock if we do not own the lock on this object.

```csharp
public void ReleaseLock()
```

### RemoveChild(sfObject) <a href="#ks_scenefusion_client_sfobject_removechild_ks_scenefusion_client_sfobject" id="ks_scenefusion_client_sfobject_removechild_ks_scenefusion_client_sfobject"></a>

Removes a child from this object. Does nothing if the child is locked, or is not found on this object.

```csharp
public override bool RemoveChild(sfObject child)
```

#### Parameters

`child` [sfObject](/scene-fusion/api-reference/ks.scenefusion.client/ks.scenefusion.client.sfobject.md)

child to remove.

#### Returns

bool

true if the child was removed successfully. Note that this does not wait for a response from the server, so it may return true and be reverted later if another user gets a lock that prevents the child removal.

### RequestLock() <a href="#ks_scenefusion_client_sfobject_requestlock" id="ks_scenefusion_client_sfobject_requestlock"></a>

Requests a lock on this object. If the object is locked by another user, tries to acquire the lock when it becomes unlocked. If the object is not syncing, call this before calling sfSession.Create to create the object with a lock.

```csharp
public void RequestLock()
```

### SetChildIndex(int) <a href="#ks_scenefusion_client_sfobject_setchildindex_system_int32" id="ks_scenefusion_client_sfobject_setchildindex_system_int32"></a>

Sets the child index, changing the object's placement in its parent's child list. Does nothing if the object has no parent, the object is locked, the index is out of bounds, or the child is already at the given index.

```csharp
public bool SetChildIndex(int index)
```

#### Parameters

`index` int

index to move child to.

#### Returns

bool

true if the child was moved successfully. Note that this does not wait for a response from the server, so it may return true and be reverted later if another user gets a lock that prevents the child move. If the child was already at the given index, returns false.

### Subscribe() <a href="#ks_scenefusion_client_sfobject_subscribe" id="ks_scenefusion_client_sfobject_subscribe"></a>

Subscribes to this object to receive its children. Does nothing if ObjectFlags.REQUIRES\_SUBSCRIPTION is not set.

```csharp
public void Subscribe()
```

### Unsubscribe() <a href="#ks_scenefusion_client_sfobject_unsubscribe" id="ks_scenefusion_client_sfobject_unsubscribe"></a>

Unsubscribes from this object to stop receiving its children. Puts all descendents of this object in the pending delete state until the server confirms our unsubscription, at which point the on confirm delete event fires for the children of this object. Does nothing if ObjectFlags.REQUIRES\_SUBSCRIPTION is not set.

```csharp
public void Unsubscribe()
```
