There are a few possible causes for this.
First, ensure that you specify the ID of the UserControlParent, the UserControlChild, and every runat="server" control in their parent hierarchy. If you miss one, ASP.NET will automatically assign one. This ID can (under certain circumstances) be different before and after your postback, thus breaking the ViewState.
Second, ensure that EnableViewState="true" for every control in the parent hierarchy, right the way up to the page. If any of them is false, it will turn off the ViewState for all its children too.
Third, as you are dynamically creating your UserControlChild, make sure you create it (and add it to UserControlParent.Controls) early enough in the page lifecycle. If you do it after the page has loaded the ViewState, you'll just get nulls back from the ViewState. Adding it in Page.Init is early enough; in Page.Load is too late.
Hope this helps!